顺序表删除相关的算法题|删除最小值|删除值为x的值|删除区间内的值|删除重复的元素(C)
删除最小值
从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值,空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行
算法思想
搜索整个顺序表,查找最小值元素并查找其位置,搜索结束后用最后一个元素填补空出的原最小值元素的位置
bool Del_Min(SqList &L, ElemType &value)
{
if (L.length == 0)
return false;
value = L.data[0];
int pos = 0;
for (int i = 1; i < L.length; i++)
{
if (L.data[i] < value)
{
value = L.data[i];
pos = i;
}
}
L.data[pos] = L.data[L.length-1];
L.length--;
return true;
}
- 函数传参通过引用传顺序表,并用过引用型参数value返回最小值
- 若删除成功,返回true,否则返回false
- 如果length为0,表示顺序表空,中止操作返回
- 假定0号元素的值最小,pos=0
- 通过for循环遍历顺序表,当i位置的值小于value,就更新value和pos
- 将length-1号元素,也就是最后一个元素赋给pos位置
- length–,表示删除最后一个元素
- 最后操作完成返回true
删除值为x的元素
对长度为n的顺序表L,编写一个时间复杂度为 O ( N ) O(N) O(N),空间复杂度为 O ( 1 ) O(1) O(1)的算法,该算法删除顺序表中所有值为x的数据元素
方法1
用k记录顺序表L中不等于x的元素个数(即需要保存的元素个数),扫描时将不等于x的元素移动到下标k的位置,并更新k值。扫描结束后修改L的长度
- 开始没有遇到值等于x的元素时
i和k一起++,将i的值前移0,也就是i自己也就是k - 遇到值等于x的元素
k停下来,不同++,与i拉开差距
因为k记录的是不等于x的值的元素个数,所以指向的是遍历过的不等于x的值的最后一个元素的下一个位置,所以之后遇到不等于x的元素直接前移到k的位置
void Del_X(SqList &L, ElemType x)
{
int k = 0;
for (int i = 0; i < L.length; i++)
{
if (L.data[i] != x)
{
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
方法2
用k记录顺序表L中等于x的元素个数,一边扫描L,一边统计k,并将不等于x的元素前移k个位置。扫描结束后修改L的长度
用i遍历顺序表中的元素
- 遇到等于x的元素
k++,记录等于x的元素个数 - 还没有遇到x时
k为0,将i位置的值前移到i-k处,也就是原位,自己赋给自己 - 遇到x之后,遇到不等于x的值
此时如果遇到x一次,k为1,将之后的不等于x的值全部前移1
如果遇到2次,k为2,同样,前移2
void Del_X(SqList &L, ElemType x)
{
int k = 0, i = 0;
while (i < L.length)
{
if (L.data[i] == x)
{
k++;
}
else
{
L.data[i-k] = L.data[i];
}
i++;
}
L.length = L.length - k;
}
方法3
src和dst一起走,还没有遇到val,src赋给dst就是自己赋给自己
dst遇到val,停下来,src继续走,跳过val值,src和dst拉开距离
src找后面不是val的值,依次尾插给dst覆盖
void removeElement(SqList &L, ElemType x) {
int src = 0, dst = 0;
while (src < L.length)
{
//不等于val,覆盖尾插到dst位置,++src,++dst
//等于val,++src相当于删除
if (L.data[src] != val)
{
L.data[dst++] = L.data[src++];
}
else
{
src++;
}
}
L.length = src;
}
删除区间内的值
从顺序表中删除其值在给定值s和t之间(包含s和t,要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示出错信息并退出运行
从前向后扫描顺序表L,用k记录值在s和t之间的元素个数(初始时k=0)。对于当前扫描的元素,若其值不在s和t之间,则前移k个位置;否则执行k++。由于每个不在s和t之间的元素仅移动一次,因此算法效率高
- 如果遍历到的值在s和t之间
k++,相当于记录值在s和t之间的元素的个数 - 之后遇到值不在s和t之间的元素时
将当前元素前移k个位置
类似之前的方法2
bool Del_s_t(SqList &L, ElemType s, ElemType t)
{
int i, k = 0;
if (L.length == 0 || s >= t)
{
return false;
}
for (i = 0; i < L.length; i++)
{
if (L.data[i] >= s && L.data[i] <= t)
{
k++;
}
else
{
L.data[i - k] = L.data[i];
}
}
L.length -= k;
return true;
}
删除重复的元素
从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同
有序顺序表,值相同的元素一定在连续的位置上,用类似于直接插入排序的思想。初始时将第一个元素视为非重复的有序表。之后依次判断后面的元素是否与前面非重复有序表的最后一个元素相同,若相同,则继续向后判断;若不同,则插入前面的非重复有序表的最后,直到判断到表尾为止。
一个指针指向第一个元素,另一个指针从第二个元素开始往后遍历
- 遇到不等于前一个元素的值
先++i,这样i和j一样,j位置的值赋给i,相当于原地赋值
然后++j,继续循环判断
- 遇到与前一个元素相等的值
i不动,j继续往后遍历
- 遇到不一样的值
先++i
再赋值
然后j++,继续循环
bool Del_Same(SqList &L)
{
if (L.length == 0)
return false;
int i, j;
for (i = 0, j = 1; i < L.length; j++)
{
if (L.data[i] != L.data[j])
{
L.data[++i] = L.data[j];
}
}
L.length = i + 1;
return true;
}
- i指向的是前面的一组不相同的元素的最后一个,所以赋值的时候需要++i,赋给下一个位置
- 每次找到与上一个元素值不同的元素,将元素前移