数据结构学习笔记:顺序表的删除操作及其演化题目总结

Posted 晚风(●•σ )

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构学习笔记:顺序表的删除操作及其演化题目总结相关的知识,希望对你有一定的参考价值。

目录

前言

文章代码皆在Dev-C++ 5.11中测试,主要是总结一些方法,从而总结一些规律使自己进一步地深化学习内容,仅供参考,若有代码错误或表述不当之处,欢迎指正!


例题

例、设计一个删除算法,删除顺序表L中的第i个位置的元素,用引用变量返回。

思路:
由于这个函数删除后顺序表L有变,所以L前要有&,且我们要返回的变量也是变化的,一开始将其初始值设置为0,所以该变量前面也要加引用。

bool ListDelete(SqList &L,int i,int &e)//bool类型的函数,用于返回true和false

首先要判断删除的元素位置i是否有效,我们知道这里的i是位序(并不是数组,数组里面从0开始;而位序从1开始),所以当i小于1且i大于顺序表的长度时显示出错信息。

if (i<1||i>L.length)
	return false; 

由于我们要删除某个元素,并通过引用变量返回,所以这里先获得位序为i的元素(i-1),并将这个位置的元素赋值给引用变量,然后这个位置就空了即被删除。

e=L.data[i-1];

删除该元素后,我们要将后面的元素都向前移动一格,这里注意,我们先移动删除元素右边的元素,而不从最后一个元素向前移,即我们可以设置一个for循环,将位序i这个量赋给j,作为j的初始值从而开始对位序为i后的元素进行向前移一格,按之前说的,所以要将数组下标大的赋值给下标小的,即

L.data[j-1]=L.data[j];

删除后顺序表要减1,并返回true表示删除成功。
核心代码如下:

/*顺序表的删除操作 (删除L中第i个位置的元素并引用变量e返回)*/
bool ListDelete(SqList &L,int i,int &e) 
	if (i<1||i>L.length)	//在[1,length+1]内有效
		return false; //删除失败返回true
	e=L.data[i-1];	//将要删除的元素赋值给e,由于是数组所以要i-1
	for(int j=i; j<L.length; j++)
		L.data[j-1]=L.data[j];	//将要删除的位置,第i个元素后的元素前移,先移动前面的元素,即下标大的赋值给下标小的
	L.length--;		//数组的长度减1
	return true; 	//删除成功后返回true

完整代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct 
	int data[MaxSize];
	int length;
 SqList;

/*初始化顺序表*/
void InitList(SqList L) 
	L.length=0;


/*顺序表的输出,从头到尾输出顺序表中各元素的值*/
void DispList(SqList L) 
	for(int i=0; i<L.length; i++)
		printf("%d ",L.data[i]);


/*顺序表的删除操作 (删除L中第i个位置的元素并引用变量e返回)*/
bool ListDelete(SqList &L,int i,int &e) 
	if (i<1||i>L.length)	//在[1,length+1]内有效
		return false; //删除失败返回true
	e=L.data[i-1];	//将要删除的元素赋值给e,由于是数组所以要i-1
	for(int j=i; j<L.length; j++)
		L.data[j-1]=L.data[j];	//将要删除的位置,第i个元素后的元素前移,先移动前面的元素,即下标大的赋值给下标小的
	L.length--;		//数组的长度减1
	return true; 	//删除成功后返回true


//主函数 
int main() 
	SqList L;
	int a;
	int e=0;	//初始化e的值 
	InitList(L);
	printf("请输入建立顺序表的元素个数:\\n");
	scanf("%d",&L.length);
	printf("请输入整数:\\n");
	for(int i=0; i<L.length; i++)
		scanf("%d",&L.data[i]);
	printf("当前顺序表为:\\n");
	DispList(L);
	printf("\\n");
	printf("请输入想删除的元素位置:\\n",a);
	scanf("%d",&a);
	if (ListDelete(L,a,e))
		printf("已删除顺序表中第%d个元素,其元素值为%d\\n",a,e);
	else
		printf("输入的位序i不合法,删除操作失败!\\n");
	printf("当前顺序表为:\\n");
	DispList(L);
	return 0;

运行结果如下:


类似题目1

例、对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法实现删除线性表中所有值为x的数据元素。

思路:
通过定义一个函数来实现要求,其参数&L是因为执行删除操作后,顺序表中的元素个数会变化,另外参数x用于输入要删除的数据元素。

void del_x(SqList &L,int x)

我们通过一个for循环,还是循环遍历整个顺序表,设置两个变量i和k,其初始值都为0,目的是找到等于和不等于值为x的数据元素,k值用于记录顺序表中不等于x的数据元素次数(这个次数最后就可以作为顺序表的最终长度),i用于循环遍历顺序表,若当前的i值不等于x时,则将当前数组下标i赋给以k为数组下标的数据元素(当找到元素时,相当于将其后数据元素的数组下标i,赋给那个被找到的数据元素,即复制一个过去),且此时k++;而若等于x时,本次for循环不执行,即本次循环的k值为顺序表中不等于x的数据元素次数。

int k=0;
for(int i=0; i<L.length; i++) 		//遍历顺序表
	if(L.data[i]!=x) 		//若不等于x,则将当前值赋给当前值;若不等于则不只需if内的语句,k值不变
		L.data[k]=L.data[i];
		k++;
	

所以最后我们得到的k=总长度-不等于x的数据元素个数,然后将这个值赋给L.length从而修改顺序表的长度,后面的元素都被剪除,从而达到删除所有值为x的数据元素的操作。

L.length=k;	//最后将k值赋给顺序表的长度,此时长度为除掉所有为x的数据元素后的值 

核心代码如下:

/*删除顺序表中所有值为x的数据元素*/
void del_x(SqList &L,int x) 
	int k=0;		//k用于记录顺序表中不等于x的数据元素
	for(int i=0; i<L.length; i++) 		//遍历顺序表
		if(L.data[i]!=x) 		//若不等于x,则将当前值赋给当前值;若不等于则不只需if内的语句,k值不变
			L.data[k]=L.data[i];
			k++;
		
	
	L.length=k;	//最后将k值赋给顺序表的长度,此时长度为除掉所有为x的数据元素后的值 

这里讲得有点繁杂,所以对代码进行一些修改,……,从而可观察每次循环后的当前顺序表,根据结果可可以更好理解执行情况,如下:

第零次循环(i=0),第一次循环没有找到与x=1相同的元素,所以顺序表无变化,i和k的值正常递加;第二次循环(i=3)找到目标元素,本次if条件语句下的内容不执行,k2值不变,此时数组下标为i3(由于是数组所以实际上为i4,后面的i和k都是一样)的数据元素替换数组下标为k2的数据元素;第三次循环正常运行,i和k的值正常递加,k为k3,i为i4;第四次循环又找到目标元素,所以此时数组下标为i4的数据元素替换数组下标为k3的数据元素,由于本次循环正常进行所以k值加1,为k4;第五次循环i=6不满足i<L.Length退出for循环,将k4的值赋给顺序表长度,后面的元素被剪除。

完整代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct 
	int data[MaxSize];
	int length;
 SqList;

/*初始化顺序表*/
void InitList(SqList L) 
	L.length=0;


/*顺序表的输出,从头到尾输出顺序表中各元素的值*/
void DispList(SqList L) 
	for(int i=0; i<L.length; i++)
		printf("%d ",L.data[i]);


/*删除顺序表中所有值为x的数据元素*/
void del_x(SqList &L,int x) 
	int k=0;		//k用于记录顺序表中不等于x的数据元素
	for(int i=0; i<L.length; i++) 		//遍历顺序表
		if(L.data[i]!=x) 		//若不等于x,则将当前值赋给当前值;若不等于则不只需if内的语句,k值不变
			L.data[k]=L.data[i];
			k++;
		
	
	L.length=k;	//最后将k值赋给顺序表的长度,此时长度为除掉所有为x的数据元素后的值 

//主函数
int main() 
	SqList L;
	int x;
	InitList(L);
	printf("请输入建立顺序表的元素个数:\\n");
	scanf("%d",&L.length);
	printf("请输入整数:\\n");
	for(int i=0; i<L.length; i++)
		scanf("%d",&L.data[i]);
	printf("当前顺序表为:\\n");
	DispList(L);
	printf("\\n");
	printf("请输入要删除顺序表中所有为x的元素值:\\n",x);
	scanf("%d",&x);
	del_x(L,x);
	printf("当前顺序表为:\\n");
	DispList(L);
	return 0;

运行结果如下:

与例题2的相似对比总结:


类似题目2

例、删除有序顺序表中重复的数据元素,使表中所有元素的值均不同。

思路:
这道题要注意输入的顺序表是有序的,通过for循环遍历有序顺序表,分别设置参数i=0及j=1,从而查找下一个与上一个元素值不相同的元素,当不相同时,将元素向前移动,然后j++;若相同则退出本次循环,然后j++,最后得到的所有元素不重复的值统计个数,赋给L.length,此时i+1前都是不重复的元素,后面多余的元素即重复元素,即完成删除顺序表中重复的数据元素。
核心代码如下:

/*删除有序顺序表中重复的元素*/
bool Delete_same1(SqList &L) 
	if(L.length==0)
		return false;
	int i,j;
	for(i=0,j=1; j<L.length; j++)
		if(L.data[i]!=L.data[j])	 //查找下一个与上个元素值不同的元素 
			L.data[++i]=L.data[j];	//找到后将元素前移动 
		
	L.length=i+1; 	//所有不重复的值的个数赋给L.length 
	return true;

对代码进行一些修改,……,从而可观察每次循环后的当前顺序表,根据结果可以更好理解执行情况,如下:

完整代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct 
	int data[MaxSize];
	int length;
 SqList;

/*初始化顺序表*/
void InitList(SqList L) 
	L.length=0;


/*顺序表的输出,从头到尾输出顺序表中各元素的值*/
void DispList(SqList L) 
	for(int i=0; i<L.length; i++)
		printf("%d ",L.data[i]);


/*删除有序顺序表中重复的元素*/
bool Delete_same1(SqList &L) 
	if(L.length==0)
		return false;
	int i,j;
	for(i=0,j=1; j<L.length; j++)
		if(L.data[i]!=L.data[j])	 //查找下一个与上个元素值不同的元素 
			L.data[++i]=L.data[j];	//找到后将元素前移动 
		
	L.length=i+1; 	//所有不重复的值的个数赋给L.length 
	return true;


//主函数
int main() 
	SqList L;
	InitList(L);
	printf("请输入建立顺序表的元素个数:\\n");
	scanf("%d",&L.length);
	printf("请输入整数:\\n");
	for(int i=0; i<L.length; i++)
		scanf("%d",&L.data[i]);
	printf("当前顺序表为:\\n");
	Delete_same1(L);
	DispList(L);
	return 0;

运行结果如下:

与例题的类似对比:


类似题目3

例、删除顺序表中重复的数据元素,使表中所有元素的值均不同。

【本题代码参考文章:https://blog.csdn.net/qq_42285148/article/details/117393638】
思路:
这题与题目2相比也就是将有序顺序表改为顺序表,设置两个for循环,从内自外循环遍历顺序表,内层循环从顺序表的第二位元素开始,跟上一题类似,不过这里是要查找下一个与上个元素值相同的元素,这里再进行分支若当前查找的下一个元素至顺序表的末尾,则将下一个元素赋值为0,且顺序表的长度减一;若不是顺序表的末尾,则继续进行一个for循环,对其中将下标大的元素赋给下标小的元素,将元素全部左移,然后再将顺序表的长度减一,最后再j–,继续回到两层for循环,检查下一个与上个元素值相同的元素。
核心代码如下:

/*删除顺序表中重复的元素*/
bool Delete_same2(SqList &L) 
	if(L.length==0)
		return false;
	int i,j,k;
	for(i=0;i<L.length;i++)	//从顺序表的第一位数据元素遍历整个顺序表
		for(j=i+1;j<L.length;j++)	//从顺序表的第二位数据元素遍历整个顺序表
			if(L.data[j]==L.data[i])	//查找下一个与上个元素值相同的元素
				if(j==L.length)	//若下一个查找的元素到顺序表的表尾
					L.data[j]=0;
					L.length--;
				
				else
					for(k=j;k<L.length;k++)	//若下一个查找的元素还没到表尾
						L.data[k]=L.data[k+1];	//将下标大的元素赋给下标小的元素
					L.length--; 	//顺序表的长度减1
				
				j--;
			
	
	return true;

完整代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct 
	int data[MaxSize];
	int length;
 SqList;

/*初始化顺序表*/
void InitList(SqList L) 
	L.length=0;


/*顺序表的输出,从头到尾输出顺序表中各元素的值*/
void DispList(SqList L) 
	for(int i=0; i<L.length; i++)
		printf("%d ",L.data[i]);


/*删除顺序表中重复的元素*/
bool Delete_same2(SqList &L) 
	if(L.length==0)
		return false;
	int i,j,k;
	for(i=0;i<L.length;i++)	//从顺序表的第一位数据元素遍历整个顺序表
		for(j=i+1;j<L.length;j++)	//从顺序表的第二位数据元素遍历整个顺序表
			if(L.data[j]==L.data[i])	//查找下一个与上个元素值相同的元素
				if(j==L.length)	//若下一个查找的元素到顺序表的表尾
					L.data[j]=0;
					L.length--;
				
				else
					for(k=j;k<L.length;k++)	//若下一个查找的元素还没到表尾
						L.data[k]=L.data[k+1];	//将下标大的元素赋给下标小的元素
					L.length--; 	//顺序表的长度减1
				
				j--;
			
	
	return true;


//主函数
int main() 
	SqList L;
	InitList(L);
	printf("请输入建立顺序表的元素个数:\\n");
	scanf("%d",&L.length);
	printf("请输入整数:\\n");
	for(int i=0; i<L.length; i++)
		scanf("%d",&L.data[i]);
	printf("当前顺序表为:\\n");
	DispList(L以上是关于数据结构学习笔记:顺序表的删除操作及其演化题目总结的主要内容,如果未能解决你的问题,请参考以下文章

数据结构学习笔记——顺序表的基本操作(超详细最终版+++)建议反复看看ヾ(≧▽≦*)o

数据结构之顺序表的插入删除操作(静态分配实现)及其时间复杂度分析

数据结构与算法学习笔记

数据结构学习笔记(栈队列)整理与总结

数据结构学习笔记(栈队列)整理与总结

数据结构代码实操04——————顺序表的总结(就是顺序表的基本操作一起用)