上一篇我们已经说过了线性表的基本实现,包括创建线性表和遍历线性表。
线性表的基本实现快速通道:
https://blog.csdn.net/Wanghh520max/article/details/137127478
本次我们来讲述对线性表进行插入和删除元素操作。
一、顺序表插入元素
向已有顺序表中插入数据元素,根据插入位置的不同,可以分为以下 3 种情况:
- 插入到顺序表的表头;
- 在表的中间位置插入元素;
- 尾随顺序表中已有元素,作为顺序表中的最后一个元素;
虽然数据元素插入顺序表中的位置有所不同,但是都使用的是同一种方式去解决,
即:通过遍历,找到数据元素要插入的位置,然后做如下两步工作:
- 将要插入位置元素以及后续的元素整体向后移动一个位置;
- 将元素放到腾出来的位置上;
例如:在{1,2,4,5,6}的第3个位置插入元素3,实现过程如下图所示:
首先遍历线性表到指定位置,即位置3.
接下来将位置3及后面的元素依次后移,空出位置3的位置。
现在我们便可以向位置3中插入指定元素3,同时线性表的长度要动态增加一。
向线性表中插入元素的代码实现如下:
SqList *Insert_SqList_tail(SqList *L) {
//判断此时线性表是否已满
if (L->length >= MaxSize) {
printf("线性表已满!");
return 0;
} else {
int site;
printf("请输入添加元素的位置:"); //自定义添加元素位置
scanf("%d",&site);
int num; //输入需要添加的元素
printf("请输入需要添加的元素:");
scanf("%d", &num);
int i;
for(i = L->length; i>=site; i--){
L->data[i] = L->data[i -1]; //遍历到要插入元素的所在位置,
} //并将目标位置后面的元素后移
L->data[site - 1] =num; //添加目标元素到线性表中
L->length ++; //线性表长度增加1
}
return L;
}
调用主函数测试函数:
int main() {
SqList L;
SqList *SP;
SP = &L;
Init_SqList(SP);
PrintSqList(Create_SqList(SP)); //打印当前的线性表
PrintSqList(Insert_SqList_tail(SP)); //打印成功添加元素后的线性表
return 0;
}
增加程序的健壮性,要是线性表长度超过MaxSzie,则无法继续插入元素。
在{1,2,4,5,6}的第3个位置插入元素3,结果如下:
二、线性表元素的查找
线性表的查找可以分为两种:按值查找和按位查找
1.按值查找
该操作是给定需要查找的元素,然后遍历线性表比较线性表中的元素是否和目标元素相等。
其时间复杂度为:
最好的情况:目标元素在表头
循环一次便可找到目标元素,时间复杂度为O(1)
最坏的情况:目标元素在表尾
需要遍历整个线性表才可找到,循环n次,时间复杂度为O(n)
平均情况:假设目标元素出现在线性表的任何一个位置的概率都相同,均是
目标元素在第1位,循环1次;在第2位,循环2次;……; 在第 n 位,循环 n 次 平均复杂度为O(n)
代码实现,我们只需遍历线性表即可。
//按值查找的代码实现
void GetElem(SqList *L) {
int num;
printf("请输入需要查找的元素:");
scanf("%d", &num);
int i;
for (i = 0; i < L->length - 1; i++) {
if (L->data[i] == num) {
printf("目标元素%d排列在线性表的第%d号位置\n", num, i + 1);
//返回的是线性表的位置,所以返回的i值需要在数组下标的基础上加1
}
}
}
若找到了则返回元素所在位置。
例:在线性表{1,2,3,4,5,6,7,8}中查找元素{5}的位置
2.按位查找
由于顺序表的各个数据元素在内存中连续存放,因此可以根据起始地址和数据元素大小立即找到第 i 个元素--“随机存取”特性。
所以按位查找的时间复杂度为O(1),一次便可以找到。
代码实现,输入目标位置即可得到目标元素。
//按位查找的代码实现
void GetElem(SqList *L) {
int site;
printf("请输入需要查找的位置:");
scanf("%d", &site);
while (true) {
//判断查找位置的合法性
if (site < 1 || site > L->length) {
//如果不合法则重新输入
printf("输入位置不合法!\n请重新输入");
printf("输入需要查找的位置:");
scanf("%d", &site);
} else {
int num = L->data[site - 1]; //注意线性表和数组下标引用的区别
printf("排列在线性表第%d号位置的元素是%d\n", site, num);
break;
}
}
}
若存在则返回元素所在位置,如果输入的位置非法则给出反馈并重新输入。
例:在线性表{1,2,3,4,5,6,7,8}中查找位于第5号的元素。
健壮性测试,输入非法位置直到合法位置后查找并退出。
三、线性表的删除操作
删除表L中第i个位置的元素,并用e返回删除元素的值。
最好情况:删除表尾元素,不需要移动其他元素。i=n,循环0次;
最好时间复杂度=0(1)
最坏情况:删除表头元素,需要将后续的n-1个元素全都向前移动i= 1,循环 n-1 次;
最坏时间复杂度=0(n);
平均情况:假设删除任何一个元素的概率相同,即i= 1,2,3,…,length 的概率都是p=1/n;
i=1,循环 n-1 次;i=2 时,循环 n-2 次;i=3,循环 n-3 次 …i=n 时,循环0次
平均时间复杂度=0(n)
代码实现,此时返回指针类型,可以在main函数中打印返回以观察是否删除成功。
//线性表删除元素操作
int *DeleteSqList(SqList *L) {
int j;
int site;
printf("请输入需要删除元素的位置:");
scanf("%d", &site);
if (site < 1 || site > L->length) { //删除位置不合法
return 0;
}
int *num = (int *) L->data[site - 1]; //接收目标位置的元素
for (j = site + 1; j <= L->length; j++)
L->data[j - 1] = L->data[j];
--L->length; // 线性表的长度减少
return num;
}
//main函数调用函数
int main() {
SqList L;
SqList *SP;
SP = &L;
Init_SqList(SP);
PrintSqList(Create_SqList(SP));
int *num = DeleteSqList(SP);
if (num != 0) {
printf("成功删除元素%d\n", num);
} else {
printf("删除失败!\n");
}
return 0;
}
例:在线性表{1,2,3,4,5,6,7,8}中删除第5号的元素.
以上便是线性表的基本操作!