数据结构(一)顺序表

news2024/11/15 10:28:22

目录

  • 一、概念
    • (一)数据结构的三元素
      • 1. 逻辑结构
        • (1)线性结构
        • (2)非线性结构
      • 2. 存储结构
        • (1)顺序存储
        • (2)链式存储
        • (3)索引存储
      • 3. 运算
    • (二)时间复杂度
      • 1. 线性阶
      • 2. 常数阶
      • 3. 平方阶
      • 4. 三次方阶
      • 5. 对数阶
      • 6. 时间复杂度排序
  • 二、顺序表
    • (一)逻辑结构
    • (二)存储结构
    • (三)操作
      • 1. 创建顺序表
        • (1)返回值是创建的顺序表
        • (2)参数传入想要创建的顺序表
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 2. 插入元素(尾插、任意位置插入)
        • (1)尾插
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
        • (2)任意位置插入
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 3. 删除元素(尾删、任意位置删除)
        • (1)尾删
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
        • (2)任意位置删除
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 4. 修改指定位置
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 5. 查找指定位置
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 6. 清空顺序表
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 7. 销毁顺序表
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 8. 排序
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 9. 翻转
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 10. 剔重
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
      • 11. 打印所有元素
          • ① 函数声明
          • ② 注意点:
          • ③代码实现
    • (四)使用C语言实现的顺序表的源代码已上传资源

一、概念

可以更合理使用内存
提高程序的执行效率

C语言本质是操作内存

数据对象、数据元素、数据项
图片

(一)数据结构的三元素

1. 逻辑结构

(1)线性结构

一对一的关系
数据连续

(2)非线性结构

树型:
一对多

图:
多对多

2. 存储结构

数据在计算机尤其是内存中的存储方式

(1)顺序存储
(2)链式存储
(3)索引存储

3. 运算

算法:有限步骤内解决问题的方法
算法不依赖于编程语言
特点:

  1. 有穷性
  2. 确定性
  3. 可行性
  4. 有0个或多个输入,有一个或多个输出

标准:

  1. 正确性
  2. 易读性
  3. 健壮性:对非法数据的处理能力
  4. 高效性
  5. 低存储

(二)时间复杂度

算法的时间复杂度定义为算法中可执行语句的频度之和 记作 T(n)
语句频度是指同一代码执行的次数
T(n)是算法所需时间的一种估值,n 表示问题的规模

算法的时间复杂度的表示方式为:
O(频度); ----------称为 大 O 表示法

假设有三段代码:
a 的时间复杂度为 2
b 的时间复杂度为 2n
c 的时间复杂度为2n^2
如果a、b、c组成一段程序,
那么算法的时间复杂度为
T(n) =T (2+2n+2n^2)
业内表示方法 还需T (2+2n+2n^2)要对进行简化

使用大O表示法的简化流程:
1.去掉运行时间中的所有常数项。
(例如 2+2n+2n^2,直接变为 2n+2n^2)
2.保留最高次幂项。
(2n^2+2n 变成 2n^2)
3.最高项存在但是系数不是1,则把系数置为1。
(2n^2 系数为2 去掉系数 n^2 )

所以,最终a、b和c合并而成的代码的时间复杂度为O(n^2)。

1. 线性阶

O(n)

2. 常数阶

O(1)

3. 平方阶

O(n^2)

4. 三次方阶

O(n^3)

5. 对数阶

O(logn)

6. 时间复杂度排序

O(1)< O(logn) < O(n) < O(nlogn) < O(n^2) <O(n^3) <O(2^n) <O(n!) < O(n^n)

可以带一个数测试,如问题规模n是16
1 < 4 < 16 < 64 < 256 < 4096 < 65536 < 16! < 16^16

二、顺序表

(一)逻辑结构

线性结构

(二)存储结构

顺序存储
内存中连续的空间

(三)操作

  • 目的:封装成函数,供他人使用
  • 结构体定义:
//节点结构体定义
typedef struct node
{
    int data; //此处以int为例,可自行添加其他成员
}Nd_t;
//列表结构体定义
typedef struct list
{
    int count; //记录当前存入了多少个值
    Nd_t listArr[MAX_SIZE]; 
}Ls_t;

1. 创建顺序表

(1)返回值是创建的顺序表

list_t *create_list_1();

(2)参数传入想要创建的顺序表
① 函数声明

int create_list(Ls_t **list);

② 注意点:
  1. 参数必须传入二级指针(需要改变main函数中的指针的值)
  2. 首先需要判定传入函数的指针是否为一个空指针(因为接下来第一件事是要使用*list来接malloc的返回值,如果传入的是一个空指针,会报段错误,所以需要提前检查)
  3. 需要判定申请空间是否成功(申请失败会返回NULL)
③代码实现
//创建顺序表并初始化
int create_list(Ls_t **list)
{
    if(NULL==list)//判定传入的指针是否是一个空指针
    {
        printf("申请空间失败\n");
        return -1;
    }
    //申请内存空间
    *list=(Ls_t *)malloc(sizeof(Ls_t));
    if(NULL==*list)//申请空间失败
    {
        printf("申请空间失败\n");
        return -1;
    }
    //初始化
    (*list)->count=0; 
    memset(*list,0,sizeof(Ls_t));

    return 0;
}
  • 补充:memset函数
#include <string.h>
void *memset(void *s, int c, size_t n);
//s 要置值的内存首地址
//c 用于置值的值
//n 置值的大小

2. 插入元素(尾插、任意位置插入)

(1)尾插
① 函数声明

int insert_list_by_tail(Ls_t *list,int num);

② 注意点:
  1. 需要判定传入的顺序表指针是否是空指针
  2. 需要判定顺序表是否已满
  3. 插入成功后,count++
③代码实现
//在尾部插入数据
int insert_list_by_tail(Ls_t *list,int num)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(MAX_SIZE == list->count)
    {
    	printf("顺序表已满\n");
    	return -1;
    }

    //插入数据
    list->listArr[list->count].data=num;
    //顺序表存入数据的数量+1
    list->count++;
    return 0;
}
(2)任意位置插入
① 函数声明

int insert_list(Ls_t *list,int pos,int num);

② 注意点:
  1. 需要判定传入的顺序表指针是否是空指针
  2. 需要判定顺序表是否已满
  3. 判定插入位置是否合法,需要大于零,且需要保证顺序表内存空间连续
  4. 插入成功后,count++
③代码实现
int insert_list(Ls_t *list,int pos,int num)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(MAX_SIZE == list->count)
    {
    	printf("顺序表已满\n");
    	return -1;
    }

    if(pos < 0 || pos > list->count)
    {
        printf("插入位置违法\n");
        return -1;
    }

    //从后往前,依次向后移动一位,直到到达插入位置
    int i=list->count;
    while(i!=pos)
    {
        list->listArr[i]=list->listArr[i-1];
        i--;
    }
    //插入数据
    list->listArr[pos].data=num;
    //顺序表存入数据的数量+1
    list->count++;
    return 0;
}

3. 删除元素(尾删、任意位置删除)

(1)尾删
① 函数声明

int delete_list_by_tail(Ls_t *list);

② 注意点:
  1. 需要判定传入的顺序表指针是否是空指针
  2. 需要判定顺序表是否已满
  3. 直接count–即可,不必去清空值,此时原来的位置相当于已经声明可以继续写入数据
③代码实现
int delete_list_by_tail(Ls_t *list)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(0==list->count)
    {
    	printf("顺序表为空\n");
    	return -1;
    }
    list->count--;
    return 0;
}
(2)任意位置删除
① 函数声明

int delete_list(Ls_t *list,int pos);

② 注意点:
  1. 需要判定列表指针是否是空指针
  2. 判断表是否为空
  3. 判定删除位置是否合法,需要大于零,且小于顺序表当前容纳值的数量;
  4. 删除成功后,count需要减一
③代码实现
int delete_list(Ls_t *list,int pos)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(0==list->count)
    {
    	printf("顺序表为空\n");
    	return -1;
    }

    if(pos<0||pos>=list->count)
    {
        printf("删除位置违法\n");
        return -1;
    }

    for(int i=pos;i<list->count;i++)
    {
        list->listArr[i]=list->listArr[i+1];
    }
    list->count--;
    return 0;
}

4. 修改指定位置

① 函数声明

int modify_list(Ls_t *list,int pos,int num);

② 注意点:
  1. 需要判定列表指针是否是空指针
  2. 判断表是否为空
  3. 判定修改位置是否合法,需要大于零,且小于顺序表当前容纳值的数量;
③代码实现
int modify_list(Ls_t *list,int pos,int num)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(0==list->count)
    {
    	printf("顺序表为空\n");
    	return -1;
    }

    if(pos<0||pos>=list->count)
    {
        printf("修改位置违法\n");
        return -1;
    }

    list->listArr[pos].data=num;
    return 0;
}

5. 查找指定位置

① 函数声明

int search_list(Ls_t *list,int pos,int *num);

② 注意点:
  1. 需要判定列表指针是否是空指针
  2. 判定查询位置是否合法,需要大于零,且小于顺序表当前容纳值的数量;
③代码实现
int search_list(Ls_t *list,int pos,int *num)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(0==list->count)
    {
    	printf("顺序表为空\n");
    	return -1;
    }

    if(pos<0||pos>=list->count)
    {
        printf("查询位置违法\n");
        return -1;
    }
    *num=list->listArr[pos].data;
    return 0;
}

6. 清空顺序表

① 函数声明

int clean_list(Ls_t *list);

② 注意点:
  1. 需要判定列表指针是否是空指针
  2. 只需将count置0即可,各函数都是根据count来进行操作,因此即使原来顺序表的值并未清空也不影响
③代码实现
int clean_list(Ls_t *list)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }
    list->count=0;
    return 0;
}

7. 销毁顺序表

① 函数声明

int destroy_list(Ls_t **list);

② 注意点:
  1. 需要先确保传入的指针并非空指针,再去判断*list是否为空
  2. 释放完堆区的空间后,再将main函数中的指针置为NULL
③代码实现
int destroy_list(Ls_t **list)
{
    if(NULL == list) 
    {
        printf("操作的指针不存在\n");
        return -1;
    }
    if(NULL == *list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }
    free(*list);
    *list=NULL;
    return 0;
}

8. 排序

① 函数声明

int sort_list(Ls_t *list,int s);

② 注意点:
  1. 先确保传入的指针并非空指针
  2. 判断表是否为空
  3. 第二个参数为0是正序排序,否则倒序排序
③代码实现
int sort_list(Ls_t *list,int s)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }
    if(0==list->count)
    {
    	printf("顺序表为空\n");
    	return -1;
    }
    int flag=0;
    for(int i=0;i<list->count-1;i++){
        flag=0;
        for(int j=0;j<list->count-1-i;j++){
            if(0==s){ //正序排序
                if(list->listArr[j].data>list->listArr[j+1].data)
                {
                    Nd_t temp=list->listArr[j];
                    list->listArr[j]=list->listArr[j+1];
                    list->listArr[j+1]=temp;
                    flag=1;
                }
            }else{
                if(list->listArr[j].data<list->listArr[j+1].data)
                {
                    Nd_t temp=list->listArr[j];
                    list->listArr[j]=list->listArr[j+1];
                    list->listArr[j+1]=temp;
                    flag=1;
                }
            }
        }
        if(0==flag) break;
    }
    return 0;
}

9. 翻转

① 函数声明

int overturn_list(Ls_t *list);

② 注意点:
  1. 先确保传入的指针并非空指针
  2. 判断表是否为空
③代码实现
int overturn_list(Ls_t *list){
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(0==list->count)
    {
    	printf("顺序表为空\n");
    	return -1;
    }
    int i=0,j=list->count-1;
    Nd_t temp;
    while(i<j)
    {
        temp=list->listArr[i];
        list->listArr[i]=list->listArr[j];
        list->listArr[j]=temp;
        i++;
        j--;
    }
    printf("翻转完成\n");
    return 0;
}

10. 剔重

① 函数声明

int dedup_list(Ls_t *list);

② 注意点:
  1. 先确保传入的指针并非空指针
  2. 判断表是否为空
  3. 两侧遍历,第一层是从第一个元素遍历到倒数第二个元素(j=i+1);第二层是从第i+1个开始遍历,然后比较与当前第i个元素是否相等,相等就删除第j个元素,后面的元素依次向前移动一个位置,此时j无需再自加1
③代码实现
int dedup_list(Ls_t *list)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    if(0==list->count)
    {
    	printf("顺序表为空\n");
    	return -1;
    }
    int i,j;
    for(i=0;i<list->count-1;i++)
    {
        for(j=i+1;j<list->count;j)
        {
            if(list->listArr[j].data==list->listArr[i].data){
                for(int k=j;k<list->count-1;k++)
                {
                    list->listArr[k]=list->listArr[k+1];
                }
                list->count--;
            }else{
                j++;
            }
        }
    }
    return 0;
}

11. 打印所有元素

① 函数声明

int show_list(Ls_t *list);

② 注意点:
  1. 需要判定列表指针是否是空指针
③代码实现
int show_list(Ls_t *list)
{
    if(NULL == list) 
    {
        printf("操作的表不存在\n");
        return -1;
    }

    for(int i=0;i<list->count;i++)
    {
        printf("%d ",list->listArr[i].data);
    }
    putchar(10);
    return 0;
}

(四)使用C语言实现的顺序表的源代码已上传资源

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1713176.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

douyin-vue:使用Vue3、Pinia和Vite5打造高度还原的抖音仿制项目

一&#xff1a;引言 在前端技术日新月异的今天&#xff0c;Vue.js作为一款流行的前端框架&#xff0c;不断吸引着开发者的目光。最近&#xff0c;GitHub上出现了一个备受瞩目的项目——douyin-vue&#xff0c;这是一个基于Vue3、Pinia和Vite5的移动端短视频项目&#xff0c;旨…

CCF20220301——未初始化警告

CCF20220301——未初始化警告 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; #define Max 100000 int x[Max]{0},y[Max]{0}; int main() {int n,k;int cnt1,flag0;cin>>n>>k;for(int i1;i<k;i)cin>>x[i]>>y[i];for(in…

Linux命令 jps(Java Process Status)解释

文章目录 1、第一种解释2、第二种解释3、第三种解释 1、第一种解释 jps 命令本身并不是一个标准的 Unix/Linux 命令&#xff0c;但您可能是想提到 jps 的一个变种或误写了 jps 为 jps&#xff0c;而实际上可能是想提及 jps&#xff08;Java Virtual Machine Process Status To…

虚拟化概述

虚拟存储器(Virtual Memory) 它的基本思想是对于一个程序来说,它的程序(code)、数据(data)和堆栈(stack)的总大小可以超过实际物理内存的大小&#xff1b;操作系统把当前使用的部分内容放到物理内存中&#xff0c;而把其他未使用的内容放到更下一级存储器&#xff0c;如硬盘&a…

通过 coze 快速构建自己的智能体机器人

通过 coze 快速构建自己的智能体机器人 coze 的使用 一&#xff09;coze 是什么 「Coze 扣子」AI Bot 开发平台。任何用户都可以快速、低门槛地搭建自己的 Chatbot&#xff0c;且平台支持用户将其一键发布到飞书、微信公众号、豆包等渠道。 二&#xff09;coze 怎么注册 1. …

安卓ADB通过WIFI无线连接手机[通过无线安装APK]

安卓ADB通过无线连接手机 本文摘录于&#xff1a;https://www.cnblogs.com/zhuxibo/p/14261117.html只是做学习备份之用&#xff0c;绝无抄袭之意&#xff0c;有疑惑请联系本人&#xff01; 别人给的操作确实可行,我这里实操记录如下: AdministratorpiaoranPC MINGW64 /e/Wor…

AI RAG的知识满天飞,为什么你还做不出一个像样的AI助手应用

引言 在过去的一年半里&#xff0c;随着大型语言模型&#xff08;LLM&#xff09;的崛起&#xff0c;检索增强生成&#xff08;RAG&#xff09;的概念也逐渐进入公众视野。 从微信公众号到各大自媒体&#xff0c;关于RAG的讨论几乎无处不在。然而&#xff0c;尽管这些高科技名…

小苯的排列构造,小苯的01背包(easy),小苯的01背包(hard)

小苯的排列构造 题目描述 运行代码 #include<bits/stdc.h> using namespace std; typedef long long ll; #define N 1000050 int i,j,k,n,m,t,a[N],b[N],f[N],l[N]; bool v[N]; int main(){cin>>n;for(i1;i<n;i)cin>>a[i];v[0]1;for(i1;i<n;i){if(a[…

apexcharts数据可视化之极坐标区域图

apexcharts数据可视化之极坐标区域图 有完整配套的Python后端代码。 本教程主要会介绍如下图形绘制方式&#xff1a; 基础极坐标区域图单色极坐标区域图 基础极坐标区域图 import ApexChart from react-apexcharts;export function BasicPolar() {// 数据序列const series…

Ubuntu/Linux 安装Paraview

文章目录 0. 卸载已有ParaView1. 安装ParaView1.1 下载后安装 2.进入opt文件夹改名3. 更改启动项4. 创建硬链接5. 添加桌面启动方式6. 即可使用 0. 卸载已有ParaView YUT 1. 安装ParaView https://www.paraview.org/ 1.1 下载后安装 找到下载的文件夹&#xff0c;文件夹内…

[JAVASE] String类 StringBuffer类 StringBuilder类

目录 一.String类 1.1 String字符串不可变的原因 1.2 字符串中的比较方法 1.2.1 equals 1.2.2 compareTo 与 compareToIgnoreCase 1.3 字符串中的查找方法 1.3.1 charAt 1.3.2 indexOf 与 lastIndexOf 1.4 字符串中的转换方法 1.4.1 valueOf 1.4.2 toUpperCase 与 to…

【PMP必考点】2024年PMP敏捷知识必考点-工件篇

PMP自2023年8月起启动了PMBOK第七版教材&#xff0c;考试内容的侧重点也发生了改变&#xff1a;大幅增加了敏捷相关的内容。以往考纲只有不到10%的敏捷管理的内容&#xff0c;新考纲的敏捷管理题目增加至50%。所以如果复习只用之前的题目是远远不够的&#xff0c;必须要多刷新考…

el-tabs中的下拉框被覆盖解决方法

解决方法&#xff1a; ::v-deep .el-tabs__content{// overflow:hidden 会导致 分页下拉框超出部分会被.el-tabs__content隐藏overflow: visible; }

JEPaaS 低代码平台 accessToTeanantInfo SQL注入漏洞复现

0x01 产品简介 JEPaaS低代码开发平台开源版 旨在帮助企业快速实现信息化和数字化转型。该平台基于可视化开发环境,让软件开发人员和业务用户通过直观的可视化界面来构建应用程序 ,而不是传统的编写代码方式。 用户可以在开发平台灵活各个图形化控件,以构建业务流程、逻辑和…

Linux基础学习笔记

目录 1、Linux安装 1.1 安装教程 1.2 Linux目录结构 2、Linux常用命令 2.1 ls 2.2 命令分类 2.3 目录处理命令 2.4 操作文件命令 2.5 查找文件命令 2.6 ln链接命令 2.7 进程相关命令 ​编辑3、配置网络 3.1 关闭windows防火墙 3.2 配置好虚拟机的局域网 3.3 配置…

[数据集][目标检测]红外兔子检测数据集VOC+YOLO格式96张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;96 标注数量(xml文件个数)&#xff1a;96 标注数量(txt文件个数)&#xff1a;96 标注类别数…

【Linux】常见命令:fping的介绍和用法举例

一、fping命令的安装 在终端中输入如下命令&#xff08;Ubuntu系统使用apt install&#xff0c;CentOS系统使用yum install&#xff09; sudo apt install fping安装效果&#xff08;截图&#xff09;&#xff1a; 二、fping命令的用法和选项 fping命令用于检测主机是否存在…

01 Nginx安装部署(系列篇)

一、安装部署 1、Nginx的发行版本 常用版本分为四大阵营&#xff1a; Nginx 开源版 | https://nginx.org/&#xff1a;赤裸裸的Web服务器、反向代理、负载均衡&#xff08;功能少&#xff0c;开发难度大&#xff09; Nginx Plus 商业版 | https://www.nginx.com/&#xff1a;…

当今世界三个最厉害的人物颜廷利:全球最受欢迎的点赞第一人

我们生活在一个历史的拐点&#xff0c;一个要求我们重新构思自我、解读世界以及预见未来的时代。在这个时代&#xff0c;那些能够洞悉社会发展的深层逻辑&#xff0c;并据此提出全新定义的人&#xff0c;将成为引领人类思维、塑造普遍价值观和主导全球发展议程的先锋。因此&…

python-合并排列数组 I

问题描述&#xff1a;合并两个按升序排列的整数数组a和b&#xff0c;形成一个新数组&#xff0c;新数组也要按升序排列。 问题示例&#xff1a;输入A[1],B[1],输出[1,1],返回合并后的数组。输入A[1,2,3,4],B[2,4,5,6],输出[1,2,2,3,4,4,5,6],返回合并所有元素后的数组。 完整代…