2.2线性表的顺序表示

本文介绍了如何从顺序表中删除具有最小值的元素、逆置表、删除特定值元素、查找并交换/插入、删除重复元素以及合并有序表等高效算法。通过一系列示例展示了在空间复杂度为O(1)或O(n)的情况下,如何处理线性表的各种操作。
摘要由CSDN通过智能技术生成

1、从顺序表中删除具有最小元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行。

bool Del_Min(sqList &L,ElemType &value){
	//删除顺序表L中最小值结点,并通过引用型参数value返回其值
	//若删除成功,则返回true;否则返回false
	if(L.length==0)		//表空,终止操作返回 
		return false;	
	value=L.data[0];	
	int pos=0;			 //假定0号元素的值最小 
	for(int i=1;i<L.length;i++){//循环,寻找具有最小值的元素 
		if(L.date[i]<value){	//让value记忆当前最小值的元素 
			value=L.data[i];	
			pos=i;
		} 
	}
	L.data[pos]=L.data[L.length-1];	//空出的位置由最后一个元素填补 
	L.length--;
	return true;  //value即为最小值 
}

2、设计一个高效的算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)
算法思想:扫描顺序表L的前半部分元素,对于元素L.data[i]与后半部分L.data[L.length-i-1]交换

void reverse(sqList &List)
{
	Elemtype temp;
	for(i=0;i<L.length/2;i++)
	{
		temp=L.data[i];
		L.data[i]=L.data[n-i-1];
		L.data[L.length-i-1]=temp;
	}
}

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

bool Del_All(sqList &L,Elemtype x){
//本算法记录值不等于x的数据元素 	
	int k=0;	//记录值不等于x的元素个数 
	for(int i=0;i<L.length;i++){
		if(L.data[i]!=value)
			L.data[k]=L.data[i];
			k++;
	}
	L.length=k;
}

4、从有序顺序表中删除其值在给定值s与t之间的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退处运行。
算法思想:先寻找值大于等于s的第一个元素(第一个要删除的元素),然后寻找值大于t的第一个元素(最后一个删除的元素的下一个元素),要将这段元素删除,只需直接将后面的元素前移

bool Del_All(sqList &L,Elemtype s,Elmetype t){
	int i,j;
	if(s>=t||L.length==0) return false;
	for(i=0;i<L.length&&L.data[i]<s;i++); //寻找值大于等于s的第一个元素 
	if(i>=L.length)
		return false;		//所有元素值均小于s,返回 
	for(j=i;j<L.length&&L.data[j]<=t;j++);//寻找大于t的第一个元素 
	for(;j<L.length;i++,j++)
		L.data[i]=L.data[j];//前移,填补被删除位置 
	L.length=i;
	return true;
	}
}

5、从顺序表中删除其值在给定值s与t之间的所有元素,如果s或不合理或者顺序表为空,则显示出错信息并退出运行。
算法思想:从前向后扫描顺序表L,用k记录下元素值在s到t之间的元素个数(初始时k=0),对于当前扫描的元素,若其值不在s到t之间,则前移k个位置;否则执行k++.由于这样每个不在s和t之间的元素仅移动一次,算法效率高

bool Del_All(sqList &L,Elemtype s,Elmetype t){
	int i,k=0;
	if(L.length==0||s>=t)
		return false;  		//线性表为空或s,t不合法,反回
	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; 
}

6、从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同
算法思想:注意是有序顺序表,值相同的元素一定在连续的位置上,用类似于直接插入排序的思想,初始时将第一个元素视为非重复的有序表。之后依次判断后面的元素是否与前面非重复有序表的最后一个元素相同,若相同则继续向后判断,若不同则插入到前面的非重复有序表的最后,直至判断到表尾为止。

bool Del(sqList &L){
	if(L.length==0)
		return false;
	int i,j;	//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;
	return false;
}

7、将2个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
算法思想:首先,按顺序不断取下2个顺序表表头较小的结点存入新的顺序表中。然后,看哪个表还剩余,将剩下的部分加到新的顺序表后面

bool Del(sqList &L){
	if(L.length==0)
		return false;
	int i,j;	//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;
	return false;
}

8、已知在一维数组A[m+n]中依次存放2个线性表(a1,a2,a3,…,am)和(b1,b2,…,bn)。试编写一个函数,将数组中两个顺序表的位置互换。
算法思想:先将数组A[m+n]中的全部元素(a1,a2,a3,…,am,b1,b2,…,bn)原地逆置,再对n个元素和后m个元素分别使用逆置算法,即可得到(b1,b2,…,bn,a1,a2,a3,…,am),从而实现顺序表的位置互换。

typedef int DataType;
void Reverse(DataType A[],int left,int right,int arraySize){
	if(left>=right||right>=arraySize)
		return;
	int mid=(left+right)/2;
	for(int i=0;i<=mid-left;i++)
	{
		Datatype temp=A[left+i];
		A[left+i]=A[right-i];
		A[right-i]=temp;
	}
}
void Exchange(DataType A[],int m,int n,int arraySize)
{
	Reverse(A,0,m+n-1,arraySize);
	Reverse(A,0,n-1,arraySize);
	Reverse(A,n,m+n-1,arraySize);
 } 

9、线性表中的元素递增有序且按顺序存储于计算机内。要求设计一算法,完成用最少时间在表查找数字为x的元素,若找到则将其与后继元素位置交换,若找不到将其插入表中元素仍递增有序。

算法思想:顺序存储的线性表递增有序,可以顺序查找,也可以折半查找。题目要求“用最少的时间在表中数值为x的元素”,这里应使用折半查找法.

void SearchExchangeInsert(ELemType A[],ElemType x){
	int low=0,high=n-1,mid;	//low和high指向顺序表下届和上届的下标 
	while(low<high){
		mid=(low+high)/2;	//找中间位置 
		if(A[mid]==x) break;	//找到x退出while循环 
		else if(A[mid]<x) low=mid+1;	//到中点mid的右半部去查 
		else high=mid-1;	//到中点mid的左半部去查 
	}
	if(A[mid]==x&&mid!=n-1){//若最后一个元素与x相等,则不存在与其后继交换的1操作 
		t=A[mid];A[mid]=A[mid+1];A[mid+1]=t;
	}
	if(low>high){	//查找失败,插入数据元素 
		for(i=n-1;i>high;i--) A[i+1]=A[i];//后移元素 
		A[i+1]=x; //插入x 
	}
}

在这里插入图片描述
在这里插入图片描述

void Reverse(int R[],int from,int to)
{
	int i,temp;
	for(i=0;i<(to-from+1)/2;i++)
	{
		temp=R[from+i];
		R[from+i]=R[to-i];
		R[to-i]=temp;
	}	
}
void Converse(int R[],int n,int p)
{
	Reverse(R,0,p-1);
	Reverse(R,p,n-1);
	Reverse(R,0,n-1);
}

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述

int M_Search(int A[],int B[],int n)
{
	int s1=0,d1=n-1,m1,s2=0,d2=n-1,m2;
	//分别表示序列A和B的首位数、末位数、中位数
	while(s1!=d1||s2!=d2){
		m1=(s1+d1)/2;
		m2=(s2+d2)/2;
		if(A[m1]==B[m2])
			return A[m1];//满足条件1 
		if(A[m1]<B[m2]){//满足条件2 
			if((s1+d1)%2==0){//若元素个数为奇数 
				s1=m1;//舍弃A中间点以前的部分且保留中间点 
				d2=m2;//舍弃 B中间点以后的部分且保留中间点 
			}
			else{//元素个数偶数 
				s1=m1+1;//舍弃A中间点及中间点以前部分 
				d2=m2;//舍弃B中间点以后部分且保留中间点 
			}
		}
		else{//满足条件3 
			if((s2+d2)%2==0){//若元素个数奇数 
				d1=m1;//舍弃A中间点以后的部分且保留中间点 
				s2=m2;//舍弃B中间点以前的部分且保留中间点 
			}
			else{
				d1=m1;
				s2=m2+1;
			}
		}
	}
	return A[s1]<B[s2]?A[s1]:B[s2]; 
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

```c
int Majority(int A[],int n){
	int i,c,count=1;	//c用来保存候选元素,count用来计数 
	c=A[0];		//设置A[0]为候选主元素 
	for(i=1;i<n;i++){	//查找候选主元素 
		if(A[i]==c)	
			count++;	//对候选主元素计数 
		else
			if(count>0)	//处理不是候选主元素的情况 
				count--;
			else{		//更换候选元素,重新计数 
				c=A[i];
				count=1;
			}
		if(count>0)
			for(i=count=0;i<n;i++) //统计候选元素出现的次数 
				if(A[i]==c)
					count++;
		if(count>n/2) return c;	//确定候选主元素的实际出现次数 
		else return -1;	//不存在主元素 
	}
}``

在这里插入图片描述
在这里插入图片描述

int findMissMin(int A[],int n){
	int i,*B;//标记数组 
	B=(int *)malloc(sizeof(int)*n);//分配空间 
	memset(B,0,sizeof(int)*n);//赋初值为0 
	for(i=0;i<n;i++)
		if(A[i]>0&&A[i]<=n)//若A[i]的值介于1-n,则标记数组B 
			B[A[i]-1]=1;
	for(i=0;i<n;i++)
		if(B[i]==0) break;//扫描数组B,找到目标值 
	return i+1;//返回结果 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值