【C语言】顺序表详解


目录

(一)顺序表是一种数据结构

(二)顺序表

(1)顺序表的必要性 

(2)顺序表的概念及结构 

 i,线性表

(3)顺序表的分类

i,顺序表和数组的区别:

ii,顺序表分类

(三)动态顺序表的实现:

 (1)头文件的解释:

(2)手把手实现动态顺序表 

a,初始化

 b,销毁

c,打印

d,扩容

e,头插与头删

 f,尾插与尾删

 g,指定位置插入与删除

h,顺序表查找某一元素


正文开始

(一)顺序表是一种数据结构

        顺序表是一种数据结构,C语言有一种内置的数据结构:数组

        当我们想要大量使用同⼀类型的数据时,通过手动定义大量的独立的变量对于程序来说,可读性非常差,我们可以借助数组这样的数据结构将大量的数据组织在⼀起,结构也可以理解为组织数据的方式。

        在我们的日常生活中,也有一些结构的概念,如 楼房,牛棚,排队的队列 等。我们希望通过一定组织,来提高查找效率。


 

 

 这都是数据结构的意义,而数据结构是什么呢?


        数据结构是计算机存储、组织数据的⽅式。数据结构是指相互之间存在⼀种或多种特定关系的数据元素的集合。数据结构反映数据的内部构成,即数据由那部分构成,以什么方式构成,以及数据元素之间呈现的结构。
 

 顺序表是基于数组的数据结构。

(二)顺序表

(1)顺序表的必要性 

         【思考】有了数组,为什么还要学习其他的数据结构?

        求数组的长度,求数组的有效数据个数,向下标为数据有效个数的位置插入数据(注意:这里是否要判断数组是否满了,满了还能继续插入吗).....

        假设数据量非常庞大,频繁的获取数组有效数据个数会影响程序执行效率。
 

         结论:最基础的数据结构能够提供的操作已经不能完全满⾜复杂算法实现。        

(2)顺序表的概念及结构 

 i,线性表

         线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是⼀种在实际中⼴泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串......

        线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

(3)顺序表的分类

i,顺序表和数组的区别:

        顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。

ii,顺序表分类

        顺序表分为静态顺序表和动态顺序表;

        a,静态顺序表

        概念:使用固定长度的数组存储数据

typedef int SLDatetype;typedef struct SList
{SLDatatype a[N];//定长数组Size_t size;//记录有效数据个数
}SL;

        b,动态顺序表

        概念:按需申请,可增容

typedef struct SList
{SLDatatype* arr;size_t size;//有效数据个数size_t capacity;//容量空间
}SL;

        通常情况下,动态顺序表的适应性更广,使用场景多。

(三)动态顺序表的实现:

         这里不加解释,直接给出头文件,根据头文件的函数声明,实现顺序表的功能:初始化,销毁,打印,扩容,头插与头删,尾插与尾删,指定位置插入与删除,以及查找顺序表的某一元素。

(共11个功能)

​#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>#define INIT_CAPACITY 4
typedef int SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{SLDataType* a;int size; // 有效数据个数int capacity; // 空间容量
}SL;//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);//头部插⼊删除 / 尾部插⼊删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);//指定位置之前插⼊/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);​

 (1)头文件的解释:

i,宏定义作为动态申请的初始值

#define INIT_CAPACITY 4

ii,顺序表内部的数据统一替换为SLDatatype,便于以后修改后复用。

typedef int SLDataType;

iii,SeqList结构体就是顺序表,重命名为SL,便于使用。

typedef struct SeqList
{
SLDataType* a;
int size; // 有效数据个数
int capacity; // 空间容量
}SL;

iv,其余为函数声明。

(2)手把手实现动态顺序表 

a,初始化

        初始化首先形参结构体指针不为空,并且将顺序表底层的数组置为空,有效数据个数和容量大小都初始为0。

void SL_init(SL* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->size = 0;
}

 b,销毁

        在使用完毕后,需要将顺序表销毁,需要将动态申请的堆区空间释放掉,有效数据个数和容量大小置为0。

void SLDestroy(SL* ps)
{assert(ps);if (ps->arr != NULL){free(ps->arr);}ps->capacity = 0;ps->size = 0;
}

c,打印

        在调试代码中,需要用打印来帮助测试函数的功能

void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}

d,扩容

        确定顺序表的容量,检查是否需要扩容,如果需要,进行将当前容量的二倍的扩容;

如何检查?

        数据是一个一个插入的,当有效数据个数等于容量的时候数据就满了,每一次插入数据,都进行一次容量是否足够的检查,若满了,就进行扩容。(插入数据都需要用此函数先检查)

第一次如何使用?

        在传入NULL时,realloc函数的作用等同于malloc函数。

void SLCheckCapacity(SL* ps)
{if (ps->capacity == ps->size){size_t Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLtype* tem = (SLtype*)realloc(ps->arr, Newcapacity * sizeof(SLtype));if (tem == NULL){perror("realloc fail");exit(1);}ps->arr = tem;ps->capacity = Newcapacity;}
}

e,头插与头删

        头插与头删:意思是在顺序表头部插入或者删除数据,由于插入数据,需要检查顺序表有效数据个数,于是要调用SL_check_capacity()函数;并且由于多了一个数据,要想将新数据插入,必须将后面的原数据后移一位:

头插:

​
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);//空间不够,扩容SL_check_capacity(ps);//空间足够,从头插入for (int i = (int)ps->size ; i > 0 ; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}​

        后移这一操作也可以用memove函数实现,

        (由于拷贝的两个空间有重叠部分,谨慎使用memcpy,memmove函数有分情况,可以解决这一问题)

        这样就省去了写for循环时考虑循环变量的范围,以及边界是否取等,以及重叠拷贝的拷贝顺序的确定,的麻烦:

​
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);//空间不够,扩容SL_check_capacity(ps);//空间足够,从头插入memmove(&ps->arr[1],&ps->arr[0],ps->size*sizeof(SLDatatype));ps->arr[0] = x;ps->size++;
}​

头删:

        删除头部的一个数据,需要将后面的数据向前移动一位:

​
void SLPopFront(SL* ps){assert(ps);assert(ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}​

同样可以用memmove函数避免麻烦:

void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);memmove(&ps->arr[0],&ps->arr[1],sizeof(SLDatatype)*(ps->size-1));ps->size--;
}

 f,尾插与尾删

        尾插与尾删:由于是在顺序表尾部插入或者删除数据,所以不需要进行数据移动,因此简单许多:

尾插:

        只需要有效数据个数加1,并将数据x存入即可;

void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//空间不够,扩容SL_check_capacity(ps);//空间足够,直接插入ps->arr[ps->size++] = x;}

尾删:

        只需要有效数据个数减少1即可;

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);ps->size--;
}

 g,指定位置插入与删除

      指定位置插入与删除:

        断言形参有效,并且传入的位置在有效数据内部;检查容量是否需要扩容;同样可以用memmove函数省时省力。

指定位置插入:

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(posi >= 0 && posi < ps->size);SL_check_capacity(ps);for (int i = (int)ps->size - 1; i >= posi; i--){ps->arr[i + 1] = ps->arr[i];}ps->arr[posi] = x;ps->size++;}

删除指定位置:

void SLErase(SL* ps, int pos)
{assert(ps);assert(posi >= 0 && posi < ps->arr);for (int i = (int)posi; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

h,顺序表查找某一元素

        查找某一元素,若找到,返回顺序表(数组)下标;找不到,返回-1;

int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1;
}

        


完~

未经作者同意禁止转载 

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

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

相关文章

Android SELinux:保护您的移动设备安全的关键

Android SELinux&#xff1a;保护您的移动设备安全的关键 1 引言 移动设备在我们的生活中扮演着越来越重要的角色&#xff0c;我们几乎把所有重要的信息都存储在这些设备上。然而&#xff0c;随着移动应用程序的数量不断增加&#xff0c;安全性也变得越来越关键。这就是为什么…

海洋鱼类检测7种YOLOV8NANO

【免费】海洋鱼类检测&#xff0c;7种类型&#xff0c;YOLOV8训练&#xff0c;转换成ONNX&#xff0c;OPENCV调用资源-CSDN文库 采用YOLOV8NANO训练模型&#xff0c;得到PT模型&#xff0c;然后转换成ONNX&#xff0c;供OPENCV的DNN调用&#xff0c;摆脱PYTORCH依赖&#xff0c…

算法设计与分析实验:最短路径算法

一、网络延迟时间 力扣第743题 本题采用最短路径的思想进行求解 1.1 具体思路 &#xff08;1&#xff09;使用邻接表表示有向图&#xff1a;首先&#xff0c;我们可以使用邻接表来表示有向图。邻接表是一种数据结构&#xff0c;用于表示图中顶点的相邻关系。在这个问题中&am…

轻松打造智能化性能测试监控平台:【JMeter+Grafana+Influxdb】的优化整合方案

在当前激烈的市场竞争中&#xff0c;创新和效率成为企业发展的核心要素之一。在这种背景下&#xff0c;如何保证产品和服务的稳定性、可靠性以及高效性就显得尤为重要。 而在软件开发过程中&#xff0c;性能测试是一项不可或缺的环节&#xff0c;它可以有效的评估一个系统、应…

C语言·贪吃蛇游戏(下)

上节我们将要完成贪吃蛇游戏所需的前置知识都学完了&#xff0c;那么这节我们就开始动手写代码了 1. 程序规划 首先我们应该规划好我们的代码文件&#xff0c;设置3个文件&#xff1a;snack.h 用来声明游戏中实现各种功能的函数&#xff0c;snack.c 用来实现函数&#xff0c;t…

探索Web3.0:下一代互联网的新篇章

随着技术的不断演进和社会的持续发展&#xff0c;我们正逐渐迈入Web3.0时代。Web3.0&#xff0c;作为下一代互联网的代名词&#xff0c;不仅仅是技术的进步&#xff0c;更是一种全新的数字化生态系统&#xff0c;其所带来的影响将深刻地改变着我们的生活、工作和交流方式。 什…

Java二维码图片识别

前言 后端识别二维码图片 代码 引入依赖 <dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.2.1</version></dependency><dependency><groupId>com.google.zxing<…

tuya-open-sdk-for-device使用体验之Windows 下 MSYS2 编译 T2-U 开发板

tuya-open-sdk-for-device 是一款跨芯片平台、操作系统的 IoT 开发框架。它基于通用南向接口设计&#xff0c;支持 Bluetooth、Wi-Fi、Ethernet 等通信协议&#xff0c;提供了物联网开发的核心功能&#xff0c;包括配网&#xff0c;激活&#xff0c;控制&#xff0c;升级等&…

2024美赛A题完整思路代码分析:建立竞争机理方程+遗传算法优化

A题是自由度比较大的场景限定下的模型构建&#xff0c;相对比较容易&#xff0c;核心是找到现有的成熟的数学模型&#xff0c;然后找到合适的数据进行证明得到结论&#xff0c;估计大部分是目标优化问题。&#xff08;不限制专业&#xff09; B题属于较为经典的物理建模&#…

【竞技宝】LOL:Able小炮连续起跳收割战场 OMG2-0轻取TT

北京时间2024年2月2日&#xff0c;英雄联盟LPL2024春季赛在昨天迎来第二周第四个比赛日&#xff0c;本日首场比赛由TT对阵OMG。本场比赛&#xff0c;TT在前中期和OMG有来有回&#xff0c;然而中后期的大龙团战始终不是OMG的对手&#xff0c;最终OMG2-0轻取TT。以下是本场比赛的…

linux vim 异常退出 异常处理 交换文件

交换文件 *.swp 格式 同时是隐藏的 如在vim一个文件&#xff0c; 在没有正常退出&#xff0c; 如直接断开连接 在次编辑这个文件 会出现下图的错误 解决方案&#xff1a; 直接删除这个交换文件即可 rm -fr .zen.txt.swp

唐墓惊现石椁,文物预防性保护系统未雨绸缪

一、文物保护的急需解决和科技的支持 陕西省考古学会近日宣布&#xff0c;考古团队在西安揭开了唐睿宗李旦孙媳妇薛柔顺墓的神秘面纱&#xff0c;其中出土的一具完整石椁&#xff0c;雕刻精湛、线条流畅&#xff0c;实属罕见珍宝。唐代石椁本就稀少&#xff0c;此次发现更是为…

RK3588开发板Ubuntu与开发板使用U盘互传

1 将 U 盘(U 盘的格式必须为 FAT32 格式&#xff0c;大小在 32G 以下)插到开发板的 usb 接口&#xff0c;串口打印信息如下所示&#xff0c;U 盘的设备节点是/dev/sdb4。U 盘的设备节点不是固定的&#xff0c;根据实际情况来查看设备节点。 2 输入以下命令挂载 U 盘&#xff0c…

Leetcode—2670. 找出不同元素数目差数组【简单】

2024每日刷题&#xff08;一零七&#xff09; Leetcode—2670. 找出不同元素数目差数组 哈希表实现代码 class Solution { public:vector<int> distinctDifferenceArray(vector<int>& nums) {unordered_set<int> s;int n nums.size();vector<int&g…

Qwen-VL 技术报告总结

感谢如此优秀的开源工作,仓库链接 Qwen-VL 权重分为 Qwen-VL && Qwen-VL-Chat,区别文档稍后介绍 训练过程 在第一阶段中主要使用224X224分辨率训练,训练数据主要来源是公开数据集,经过清洗,数据总量大约是1.4B,中文数据和英文j训练目标是视觉语言和文本语言对齐。…

docker集成 nacos/nacos-server (包括踩的坑)

tips 这边需要的数据库我已经安装好了&#xff0c;所以数据库的安装这边已经省略了 拉取镜像&#xff08;这边使用nacos1.4.1作为例子&#xff09; docker pull nacos/nacos-server:1.4.1创建映射的文件夹 (conf存放配置文件&#xff0c;logs存放日志文件) mkdir -p /data/n…

MySQL索引的原理和SQL优化策略

1. 索引 在InnoDB存储引擎中&#xff0c;索引分为聚簇索引和辅助索引两种类型。 聚簇索引是指基于表的主键构建的索引&#xff0c;它决定了表中数据的物理存储顺序。也就是说&#xff0c;聚簇索引中的键值按照主键的顺序来排序&#xff0c;并且每个叶子节点存储的是整个表行的…

HAL库配置PWM模式

一、什么是PWM 脉冲宽度调制(PWM)&#xff0c;是英文“Pulse Width Modulation”的缩写&#xff0c;简称脉宽调制。通过控制高低电平在一个周期内的占比从而输出一定的电压。 向上计数原理介绍 ​PWM的一个周期 定时器从0开始向上计数 当0-t1段,定时器计数器TIMx_CNT值小于…

直播团队职责

一、内容策划 直播团队的内容策划人员是整个直播活动的核心&#xff0c;他们需要负责策划直播的主题、内容、形式以及时间安排等。同时&#xff0c;他们还需要负责邀请嘉宾、安排活动等&#xff0c;确保直播内容丰富、有趣、有价值。 二、主播管理 主播是直播活动的关键人物…

unity WebGL发布游戏生成WebGL

1.unty Hub中安装WEBGL支持 2.项目平台的切换 color space需要根据项目选择 ColorSpace&#xff0c;是指玩家设置的颜色空间。 伽马颜色空间是历史悠久的标准格式&#xff0c;但线性颜色空间渲染可提供更精确的结果。 具体区别&#xff1a;ColorSpace 3.由于没有自己服务器…