首先,我们的顺序表是由一个存放数据的数组和一个存放数组最后的一个元素的下标也就是last构成。
具体形式如图
![](https://img-blog.csdnimg.cn/img_convert/3bcf47e50d69ea96276ebdf2a6c6d932.png)
如图,last指向顺序表最后一个元素,我们可以看出此时顺序表中有两个数是有重复的,但我们在实际运算的过程中可能并不知道,我们可以对顺序表进行遍历,定义一个i当作被比较数,定义一个j为比较数,当然j肯定是在i后面一位,因为i没有必要和前面的数以及自己比较,我们是向后面进行遍历的,那么,我们的思路是,i首先指向第一个数据,j也就指向第二个数据,然后将i与j的数据进行比较,如果i与j的数据不相等,也就是说它们不重复,不是我们要删除的对象,我们可以让i不变,j进行++,使其指向后面一位数据,直到j指向最后一个数据,也就是last。
如图,
![](https://img-blog.csdnimg.cn/img_convert/8beceb3b0a67f7fd80ae4ac0f0ee301d.png)
当j一直++到与last相等也就是j指向最后一个数据时,如果i与j的数据仍然不相等的话,那我们可以知道在整个顺序表中,没有一个数据与i所指向的数据相等,我们可以不考虑它了,于是将i进行++,使其指向下一位,然后再重复上述步骤,继续与后面的数据比较,直到i的数据与j的数据相等时,如图
![](https://img-blog.csdnimg.cn/img_convert/b7fb627231119b1aa4eeadf925b75ccf.png)
我们不难看出在进行一轮遍历后,i指向的数据为2,而j指向的数据也为2,它们重复,这时候我们可以开始删除元素了,我们有两个选择,第一是删除i所指,第二是删除j所指,那么在这里有什么区别呢,不妨想象一下,假如我们删除的是i,那么i后面的所有元素全部往前移动一位,如图所示
![](https://img-blog.csdnimg.cn/img_convert/4f582299fc61988ae75ebb82524a7a96.png)
代码为
if(L->data[i] == L->data[j]) //如果i与j的数据相同
{
for(int temp = i;temp < L->last;temp++) //将i后面的数据全部往前移一位
{
L->data[temp] = L->data[temp+1];
}
L->last--; //之后将last--,因为last始终指向最后一位
}
那么,i的删除就“完成了”,我们不妨接着往下看,看看我们是否大意
![](https://img-blog.csdnimg.cn/img_convert/5b0d92dc294b10d249e03a1bb44c96be.png)
将i所指向的数据删除后,实际上现在i指向的是之前j的数据,而j所指向的是之前j+1的数据,这里因为将后面的数据都往前移一位,所以数组的下标产生了变化。随后j再进行++,知道j又指向了与i所指向数据相等的数据,和之前一样,我们继续把i所指向的数据删除,如图
![](https://img-blog.csdnimg.cn/img_convert/1870827991946289639c1b7f39b995ea.png)
这里依然是数组的下标发生了改变,那么我们在判断j所指向的数据5与i所指向的2不一致后,一轮遍历结束,那么我们的i进行++!!!!!j依然为i+1!!!!!!
关键就在这,在i所指向数据删除后,i指向了被删除数据的下一个数据,也就是上图的3,但是在j遍历完发现没有数据与i所指数据相等后,i进行了++,如图
![](https://img-blog.csdnimg.cn/img_convert/269f99612834c27b1d39184dd8914571.png)
我们可以看到i跳过了3,于是我们将会输出1,3,3,4,2,5
这显然不是我们所希望的,很多同学(包括我),就在这里出了一个bug
那我们如何避免呢,我们可以这样
if(L->data[i] == L->data[j]) //如果i与j的数据相同
{
for(int temp = i;temp < L->last;temp++) //将i后面的数据全部往前移一位
{
L->data[temp] = L->data[temp+1];
}
L->last--; //之后将last--,因为last始终指向最后一位
i--; //将i“归位”
}
与上一段代码相比呢,多了一句i--,那么它的作用就在于“复位”,也就是阻止其指向下一位,因为这一位被删除了,我们要让下一次遍历i所指向的仍然是被删除的下一位,而不是跳过它,如图:
![](https://img-blog.csdnimg.cn/img_convert/96d123e6201340ea2af87842edb53d1d.png)
当然,我们也可以直接删除j
if(L->data[i] == L->data[j]) //如果i与j的数据相同
{
for(int temp = j;temp < L->last;temp++) //将j后面的数据全部往前移一位
{
L->data[temp] = L->data[temp+1];
}
L->last--; //之后将last--,因为last始终指向最后一位
}
好的,我们今天的分享就到这里,感谢大家于百忙之中得到微之甚微的知识,下面附赠顺序表的源码,只有简单的增删查改接口,其余的大家一起动手来实现吧!
#include<stdio.h>
#include<stdlib.h>
#include"shun.h"
#include<string.h>
SqLink InitList() //顺序表初始化
{
SqLink L;
L = (SqLink)malloc(sizeof(SqList)); //申请地址
if(L == NULL){
printf("malloc error!\n");
return L;
}
memset(L,0,sizeof(SqList)); //将长度为sizeof(SqList)的顺序表元素全部赋值为0
L->last = -1;
return L;
}
int List_Show(SqLink L) //顺序表的展示
{
if(L == NULL||L->last == -1){
printf("Nothing can show!\n");
return -1;
}
for(int i = 0;i<=L->last;i++)
{
printf("%d ",L->data[i]);
}
puts("");
return 0;
}
int List_Insert(SqLink L,int sub,DataType num) //顺序表的插入
{
if(L == NULL){
printf("List NULL!\n");
return -1;
}
if(L->last == MAXLEN-1){
printf("List Full!\n");
return -1;
}
if(sub<0||sub>L->last+1){
printf("sub error!\n");
return -1;
}
if(L->last == -1)
{
L->last++;
L->data[L->last] = num;
return 0;
}
for(int i = L->last;i>=sub;i--){
L->data[i+1] = L->data[i];
}
L->data[sub] = num;
L->last++;
return 0;
}
int List_Delete(SqLink L,int sub) //顺序表的删除
{
if(L == NULL||L->last == -1){
printf("List Nothing can delete!\n");
return -1;
}
for(int i = sub;i<L->last;i++)
{
L->data[i] =L->data[i+1];
}
L->last--;
return 0;
}
int List_Find(SqLink L,DataType num) //查找顺序表中的某一元素,可能为多个
{
int temp = 0;
if(L == NULL||L->last == -1){
printf("List is NULL!\n");
return -1;
}
for(int i = 0;i<=L->last;i++)
{
if(L->data[i] == num){
printf("num is %d,sub is %d\n",L->data[i],i);
temp++;
}
}
if(temp == 0)
printf("Not fount!\n");
return 0;
}
int List_Change(SqLink L,int sub,DataType num) //顺序表的修改
{
if(L == NULL||L->last == -1){
printf("Nothing can change!\n");
return -1;
}
L->data[sub] = num;
return 0;
}
int List_Norepist_Norep(sq L) //删除相同元素
{
if(L == NULL){
printf("error\n");
return 0;
}
for(int i = 0;i<L->last;i++)
{
for(int j = i+1;j<=L->last;j++)
{
if(L->data[i] == L->data[j])
{
for(int temp = i;temp<L->last;temp++)
{
L->data[temp] = L->data[temp+1];
}
L->last--;
i--;
}
}
}
return 0;
}