题目再现
设计一个算法,删除顺序表L中所有具有给定值x的元素
测试效果
解题思路
算法用指针i向后继方向逐个检查顺序表中元素,用k记录压缩含x结点以后的后续结点应移动到哪个位置。一趟扫描完成删除顺序表所有含x结点的元素。
按照复合条件判断的短路原则,当L.data[i]==x时不再判++k!=i.算法时间复杂度为O(n).最好情况是序列中没有值等于x的元素或所有元素的值都等于x,不需要移动元素.
核心源码
void deleteValue(SeqList& L,DataType x) {
int k = -1;
for(int i =0;i<L.n;i++)
if(L.data[i] != x && ++k != i)
L.data[k] = L.data[i];
L.n = k+1;
}
复杂度分析
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
完整源码
#include<stdio.h>
#include<stdlib.h>
#define initSize 100
typedef int DataType;
typedef struct{
DataType *data;
int maxSize,n;
}SeqList;
void initList(SeqList& L) {
//调用方式initList(L),输入:未初始化的顺序表L;输出;已初始化的顺序表L
L.data = (DataType *) malloc(initSize*sizeof(DataType));
if(!L.data) {
printf("分配有误....\n");
exit(1);
}
L.maxSize = initSize;
L.n = 0;
}
void createList(SeqList &L,DataType A[],int n) {
initList(L);
for(int i = 0;i<n;i++)
L.data[i] = A[i];
L.n = n;
}
void printList(SeqList& L) {
for(int i =0;i<L.n;i++)
printf("%d ",L.data[i]);
printf("\n");
}
//设计一个算法,删除顺序表L中所有具有给定值X的元素
void deleteValue(SeqList& L,DataType x) {
int k = -1;
for(int i =0;i<L.n;i++)
if(L.data[i] != x && ++k != i)
L.data[k] = L.data[i];
L.n = k+1;
}
int main()
{
SeqList A,B;
//模拟1的情况
int arr1[5] = {
5,2,9,2,1};
createList(A,arr1,sizeof(arr1)/sizeof(int));
printList(A);
deleteValue(A,2);
printf("deleted:..\n");
printList(A);
return 0;
}
源码跑路
假如我们输入的是{5,2,9,2,1},传入删除2按照代码的正常运行结果是{5,9,1}
i = 0
L.data[0] = 5 != 2 && ++(-1) == 0
for循环继续 k = 0
i = 1
L.data[1] == 2
for循环继续 k = 0
i = 2
L.data[2] = 9 != 2 && 1 != 2
L.data[1] = L.data[2]
这里已经发生前移,本质上利用了i和k的差值进行赋值
for循环继续 k=1
i = 3
L.data[3]=2 == 2
for 循环继续 k=1
i = 4
L.data[4] = 1 != 2 && 2 != 4
L.data[2] = L.data[4]
for 循环继续 k = 2
i = 5 跳出循环!
参考文献
殷人昆著.数据结构与算法解析.北京:清华大学出版社,2021.4
临别赠语
挺巧妙的一个算法,利用了彼此的差值,进行赋值!