数据结构中的顺序表
顺序表
数据结构中的物理结构(存储结构)分为顺序结构和链式结构。
- 顺序结构:是在内存中申请一块连续的空间来存储数据(可以理解为数组),一般情况下都是在堆内存申请空间。
下面是如何创建顺序表:
- 一般情况下,需要有几个变量记录顺序表的数据(如顺序表的长度、顺序表存储的元素个数,顺序表的首地址),这些数据使用一个结构体来存储即可。

//顺序表存放的数据类型,使用这个类型可以在这修改顺序表中存储的数据类型
typedef int DataType_t;
//1.需要建立顺序表的管理结构体
typedef struct seqlist
{
DataType_t * Addr; //顺序表的首地址
unsigned int Size; //顺序表的容量
int Last; //顺序表的存储个数
}Seqlist_t;
- 第二步就是创建顺序表
/****************************************************
* 函数名称: SeqList_Create
* 函数功能: 新建顺序表
* 函数参数:
* @size:创建顺序表的大小
* 返回结果: 返回顺序表管理者的地址
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
Seqlist_t * SeqList_Create(unsigned int size)
{
//1.首先需要一个管理者
Seqlist_t * Manager = (Seqlist_t *)calloc(1,sizeof(Seqlist_t));
if(NULL == Manager){
perror("calloc for Manager is failed!!!");
exit(-1);
}
//2.建立顺序表的堆空间,堆空间的首地址由管理者的addr成员管理
Manager->Addr = (DataType_t*) calloc(size,sizeof(DataType_t));
if(NULL == Manager->Addr){
perror("calloc for Manager is failed!!!");
free(Manager);
Manager = NULL;
exit(-1);
}
//3.顺序表创建完成需要初始化
Manager->Size = size;
//元素的下标从-1开始表示没有元素
Manager->Last = -1;
return Manager;
}
- 有了顺序表接下来就是对顺序表进行增删改查。
顺序表元素的插入
为顺序表添加元素,添加元素有三种情况,在尾部添加,中间添加,头部添加。时间复杂度依次增加,因为需要遍历的元素增加。
- 首先在尾部添加,这是最简单的情况,一共两个函数,第一个是判断顺序表是否已满,第二个是在尾部添加元素。

/****************************************************
* 函数名称: SeqList_IsFull
* 函数功能: 判断顺序表是否已满
* 函数参数:
* @Manager:顺序表管理者的地址
* 返回结果: true:已满。false:未满。
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_IsFull(Seqlist_t * Manager)
{
return (Manager->Last+1 == Manager->Size) ? true : false ;
}
/****************************************************
* 函数名称: SeqList_TailAddEle
* 函数功能: 给顺序表尾部添加新的元素
* 函数参数:
* @Manager:顺序表管理者的地址
* @data :添加的数据
* 返回结果: true:添加成功。false:添加失败。
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_TailAddEle(Seqlist_t * Manager,DataType_t data)
{
//1.首先判断顺序表是否已满
if( SeqList_IsFull(Manager) ){
printf("sequence list is full!\n");
return false;
}
//2.未满可以插入,在尾部插入,插入完成之后也需要个数需要加一
Manager->Addr[++Manager->Last] = data;//给最后一个元素赋值后加一
return true;
}
- 第二是在中间添加,把需要插入的地方的元素,以及后面的元素向后移动一位即可。

/****************************************************
* 函数名称: SeqList_MediumAddEle
* 函数功能: 给顺序表中间添加新的元素
* 函数参数:
* @Manager :顺序表管理者的地址
* @data :添加的数据
* @dest_data :需要在第几个数据后面添加
* 返回结果: true:添加成功。false:添加失败。
* 注意事项: 在中间插入后其余元素会滞后。
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_MediumAddEle(Seqlist_t * Manager,DataType_t dest_data,DataType_t data)
{
//1.首先判断顺序表是否已满
if( SeqList_IsFull(Manager) ){
printf("sequence list is full!\n");
return false;
}
int num = 0;
//2.先寻找到这个数据所在的位置,需要记住元素所在的位置
for(num = 0;(dest_data != Manager->Addr[num]) && (num < Manager->Last);num++);
//判断是否有这个数据
if((num == Manager->Last) && (dest_data != Manager->Addr[num])){
printf("dest_data(%d) is exist!!!\n",dest_data);
return false;
}
//判断是否为顺序表最后一个,最后一个不需要移动直接添加
if(num == (Manager->Last)){
Manager->Addr[num+1] = data;
Manager->Last++;
return true;
}
//3.将指定的位置以及后面都向后移动
for(int j = Manager->Last;j > num;j--){
Manager->Addr[j+1] = Manager->Addr[j];
}
//4.将元素赋值给这个下标的位置,并且元素个数加一
Manager->Addr[num+1] = data;
Manager->Last++;
return true;
}
- 最后是在头部插入,需要把所有的元素向后偏移

/****************************************************
* 函数名称: SeqList_HeadAddEle
* 函数功能: 给顺序表头部添加新的元素
* 函数参数:
* @Manager:顺序表管理者的地址
* @data :添加的数据
* 返回结果: true:添加成功。false:添加失败。
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_HeadAddEle(Seqlist_t * Manager,DataType_t data)
{
//1.首先判断顺序表是否已满
if( SeqList_IsFull(Manager) ){
printf("sequence list is full!\n");
return false;
}
//2.没有满需要把前面的元素往后挪
for(int i = Manager->Last;i >= 0;i--){
Manager->Addr[i+1] = Manager->Addr[i];
}
//3.移动之后,第一个元素空闲,直接放置数据,别忘记数据加一
Manager->Addr[0] = data;
Manager->Last++;
return true;
}
顺序表元素的删除
接下来是删除元素,删除元素也是分为了三种,尾部插入、中间插入、头部插入,时间复杂度也是依次增加。
- 尾部删除,直接把有效数据的下标减一即可。每一次删除元素都需要判断顺序表是否有元素

/****************************************************
* 函数名称: SeqList_IsEmpty
* 函数功能: 判断顺序表是否为空
* 函数参数:
* @Manager:顺序表管理者的地址
* 返回结果: true:为空。false:不为空。
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_IsEmpty(Seqlist_t * Manager)
{
return (Manager->Last == -1) ? true : false ;
}
/****************************************************
* 函数名称: SeqList_TailDelEle
* 函数功能: 在顺序表的尾部删除元素
* 函数参数:
* @Manager:顺序表管理者的地址
* 返回结果: true:删除成功。false:删除失败。
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_TailDelEle(Seqlist_t * Manager)
{
//1.首先需要顺序表是否为空
if(SeqList_IsEmpty(Manager)){
printf("sequence list is empty!\n");
return false;
}
Manager->Last--;
return true;
}
- 中间删除元素。

/****************************************************
* 函数名称: SeqList_MediumDelEle
* 函数功能: 在顺序表的中间删除元素
* 函数参数:
* @Manager :顺序表管理者的地址
* @data :需要删除的数据
* 返回结果: true:删除成功。false:删除失败。
* 注意事项: 后面的数据会向前覆盖,数据的部分下标会发生变化
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_MediumDelEle(Seqlist_t * Manager,DataType_t data)
{
//1.首先需要顺序表是否为空
if(SeqList_IsEmpty(Manager)){
printf("sequence list is empty!\n");
return false;
}
//2.先寻找到数据,并且记住元素的下标
int num = 0;
for(num = 0;(data != Manager->Addr[num]) && (num < Manager->Last);num++);
//判断是否有这个数据
if((num == Manager->Last) && (data != Manager->Addr[num])){
printf("data(%d) is exist!!!\n",data);
return false;
}
//判断是否为最后一个元素
if( num == Manager->Last){
//把有效数据下标减一
Manager->Last--;
return true;
}
//3.把数据向前覆盖
for(int i = num;i < Manager->Last;i++){
Manager->Addr[i] = Manager->Addr[i+1];
}
//4.把有效数据下标减一
Manager->Last--;
return true;
}
- 头部删除元素

/****************************************************
* 函数名称: SeqList_HeadDelEle
* 函数功能: 在顺序表的头部删除元素
* 函数参数:
* @Manager:顺序表管理者的地址
* 返回结果: true:删除成功。false:删除失败。
* 注意事项: 后面的数据会向前覆盖,数据的下标会发生变化
* 函数作者:
* 创建日期: 2024/04/19
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_HeadDelEle(Seqlist_t * Manager)
{
//1.首先需要顺序表是否为空
if(SeqList_IsEmpty(Manager)){
printf("sequence list is empty!\n");
return false;
}
//2.把数据向前覆盖
for(int i = 0;i < Manager->Last;i++){
Manager->Addr[i] = Manager->Addr[i+1];
}
//3.把有效数据下标减一
Manager->Last--;
return true;
}
顺序表元素的修改
接下来是修改元素,修改元素分为两个,第一个是根据数据修改(相同的数据也会被修改),第二个是下标修改
- 数据修改
/***************************************************
* 函数名称: SeqList_DataRecEle
* 函数功能: 按元素的数据修改元素
* 函数参数:
* @Manager :顺序表管理者的地址
* @scr_data :顺序表中的数据,源数据
* @desk_daat :需要修改的数据,目标数据
* 返回结果: true:修改成功。false:修改失败。
* 注意事项: 所有相同的元素都会修改成dest_data
* 函数作者:
* 创建日期: 2024/04/20
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_DataRecEle(Seqlist_t * Manager,DataType_t scr_data,DataType_t desk_daat)
{
//1.首先需要顺序表是否为空
if(SeqList_IsEmpty(Manager)){
printf("sequence list is empty!\n");
return false;
}
int cnt = 0;//计算修改的次数
//2.查找到顺序表中相同的元素进行修改
for(int i = 0;i <= Manager->Last ;i++){
if(Manager->Addr[i] == scr_data){
Manager->Addr[i] = desk_daat;
cnt++;
}
}
//没有修改到元素,没有查找到这个数据
if(cnt == 0){
printf("scr_data(%d) is exist!!!\n",scr_data);
return false;
}
return true;
}
- 下标修改
/****************************************************
* 函数名称: SeqList_SubRecEle(rectify)
* 函数功能: 按元素的下标修改元素
* 函数参数:
* @Manager :顺序表管理者的地址
* @num :需要修改数据元素的下标
* @data :需要修改的数据,目标数据
* 返回结果: true:修改成功。false:修改失败。
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/20
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_SubRecEle(Seqlist_t * Manager,unsigned int num,DataType_t data)
{
//1.首先需要顺序表是否为空
if(SeqList_IsEmpty(Manager)){
printf("sequence list is empty!\n");
return false;
}
//2.判断下标是否有效
if(num > Manager->Last){
printf("num(%d) is invalid!\n",num);
return false;
}
//2.直接根据下标修改元素
Manager->Addr[num] = data;
return true;
}
顺序表元素的查找
顺序表元素的查找使用下标查找元素
- 下标查找元素,返回元素的数据
/****************************************************
* 函数名称: SeqList_SubDeteEle
* 函数功能: 按元素的下标查找元素
* 函数参数:
* @Manager:顺序表管理者的地址
* @num :下标
* 返回结果: 返回查找的数据,顺序表为空不返回值
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/20
* 修改历史:
* 函数版本: V1.0
***************************************************/
DataType_t SeqList_SubDeteEle(Seqlist_t * Manager,unsigned int num)
{
//1.首先需要顺序表是否为空
if(SeqList_IsEmpty(Manager)){
printf("sequence list is empty!\n");
return ;
}
//判断下标是否有效
if(num > Manager->Last){
printf("num(%d) is invalid!\n",num);
return ;
}
return Manager->Addr[num];
}
顺序表的删除
完成顺序表元素的增删改查之后,别忘记顺序表是从堆区申请的内存,需要程序员手动释放
/***************************************************
* 函数名称: SeqList_Dle
* 函数功能: 删除顺序表
* 函数参数:
* @Manager :顺序表管理者的地址
* 返回结果: true:删除成功。false:删除失败。
* 注意事项: None
* 函数作者:
* 创建日期: 2024/04/20
* 修改历史:
* 函数版本: V1.0
***************************************************/
bool SeqList_Dle(Seqlist_t * Manager)
{
//1.判断管理者是否存在
if(NULL == Manager){
printf("sequence list is no exist");
return false;
}
//2.先把顺序表删除,在删除管理者
free(Manager->Addr);
Manager->Addr = NULL;
free(Manager);
Manager = NULL;
return true;
}
- 需要的头文件
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
- 顺序表到这里就结束了,更多的功能可以自己加上去。

浙公网安备 33010602011771号