C语言顺序表插入与删除操作详解
顺序表是C语言数据结构中最基础的线性结构之一。本文详细拆解如何使用指针和动态内存实现顺序表的初始化、按位插入(含空间不足时的扩容逻辑)以及元素删除。通过完整的C语言代码示例,直观展示数据元素在数组中的移动过程,适合需要理解底层内存管理的开发者参考。
一、理解顺序表结构与初始化
顺序表本质上是利用连续内存存储数据的结构。在C语言中,通常使用 struct 封装一个指向动态数组的指针,并记录当前有效长度与总容量。
第1步:定义数据结构
首先定义顺序表的结构体。需要注意,listsize 表示分配的总容量,而 len 记录实际存放的有效元素个数。在逻辑上,顺序表的第一个元素通常被视为位置 1,这与 C 语言数组从索引 0 开始的物理特性存在偏移关系。
<stdio.h> 用于输入输出,<stdlib.h> 用于动态内存管理。Elemtype 定义为整型,可根据实际需求修改。
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define OK 1
#define FALSE 0
typedef int Elemtype;
typedef bool Status;
typedef struct list
{
Elemtype *elem;
int len; //数据个数
int listsize; //顺序表长度
}List;
第2步:初始化函数
初始化函数的核心是申请初始内存并设置状态参数。若内存申请失败,程序应立即退出以防后续操作引发严重错误。
void list_init(List *L)
{
L->elem=(Elemtype *)malloc(MAXSIZE*sizeof(Elemtype));
if(L->elem==NULL)
{
printf("malloc fail\n");
exit(0);
}
L->len=0; //初始化有效数据长度为0
L->listsize=MAXSIZE; //初始化总容量
}
二、顺序表的插入操作
插入操作不仅要处理数据的前移,还要考虑当前存储空间是否足够。插入的逻辑步骤如下:
第3步:位置校验与扩容检查
插入位置 i 必须合法,即大于等于 1 且小于等于当前长度加 1。同时需判断当前长度是否已达到上限 listsize。若空间已满,则需要调用 realloc 进行动态扩容,增加一块大小为 MAXSIZE 的空间,并更新 listsize。
Status list_insert(List *L,int i,Elemtype data)
{
Elemtype *base,*insert,*p;
// 1. 合法性检查
if(i<1 || i>L->len+1 || L==NULL)
{
printf("位置输入错误\n");
return FALSE;
}
// 2. 空间不足时扩容
if(L->len >= L->listsize) // 原文此处逻辑有误,应为>=或已接近满员才扩容
{
base=(Elemtype *)realloc(L->elem,(L->listsize+MAXSIZE)*sizeof(Elemtype));
if (base == NULL) { // 建议增加 realloc 失败检查
printf("realloc fail\n");
return FALSE;
}
L->elem=base;
L->listsize+=MAXSIZE;
}
// ... 后续移动数据代码略
}
第4步:后移元素并赋值
找到目标插入地址 insert(对应数组索引 i-1)。从最后一个有效元素开始,逐个将元素向后移动一位,直到移动到 insert 位置的下一个位置。最后将新数据写入 insert 指向的地址,并将有效长度 len 加 1。
insert=&(L->elem[i-1]); // 获取插入位置指针
// 从最后一个元素前移,直到移到插入位置之后
for(p=L->elem + L->len-1;p>=insert;p--)
{
*(p+1)=*p;
}
*insert=data;
L->len++;
return OK;
三、顺序表的删除操作
删除指定位置的元素后,需要将后继元素向前填补空缺。若删除位置非法(如越界),则直接返回失败。
第5步:定位与移位
获取待删除元素的指针 aim(数组索引 i-1)。随后从 aim+1 位置开始,将每个元素赋值给前一个位置,直至遍历完所有剩余元素。操作完成后,有效长度 len 减 1。
Status list_delete(List *L,int i)
{
Elemtype *aim,*p;
// 1. 参数校验
if(i<1 || i>L->len)
{
printf("位置输入错误\n");
return FALSE;
}
// 2. 定位删除元素
aim=&(L->elem[i-1]);
p=(L->elem+L->len-1); // 指向末尾元素的指针
// 3. 覆盖式前移
for(aim=aim+1;aim<=p;++aim)
{
*(aim-1)=*aim;
}
L->len--;
return OK;
}
四、完整示例与验证
以下代码整合了上述逻辑,包含显示列表的功能以及 main 测试用例。程序中先在顺序表中存入 10 个元素,然后在第 5 个位置插入 99,最后再删除第 5 个位置的元素。执行后可观察数据的变化以验证逻辑的正确性。
// 补充显示函数
void show_list(List *L)
{
int i;
for(i=0;i<L->len;i++)
{
printf("elem[%d]=%d\n",i+1,L->elem[i]);
}
printf("\n");
}
int main()
{
int i;
List L;
list_init(&L);
// 初始插入 1 到 10
for(i=0;i<10;i++)
{
list_insert(&L,i+1,i+1);
}
printf("插入前的顺序表\n");
show_list(&L);
printf("在第5位置插入99后的顺序表\n");
list_insert(&L,5,99);
show_list(&L);
printf("删除第5位置元素后的顺序表\n");
list_delete(&L,5);
show_list(&L);
return 0;
}
通过上述步骤,可以清晰看到顺序表在内存中连续的存储特性及其插入、删除操作的移动代价。在实际工程开发中,建议对动态扩容的时机进行优化(例如增长比例为 1.5 倍而非固定增量),以提升性能。
以上就是C语言实现顺序表的插入删除的详细内容,更多关于C语言数据结构线性表操作的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









