王道线性表2.24

本文详细介绍了数组的各种操作,如初始化、插入、删除、查找、排序等,并提供了C++实现。涉及到静态链表和动态链表的区别,以及如何进行空间管理。还探讨了寻找数组中位数、主元素和最小值的算法。每个操作都有清晰的思路和代码示例。
摘要由CSDN通过智能技术生成

提示 他日若是同淋雪 此生亦算共白头


对比

首先无论是静态链表还是动态链表都是需要三个信息,一个是链表中的实际长度Length,一个是最大长度MaxSize,静态的时候是通过在结构体中设置一个数组,判断实际长度Length与其中的最大长度作对比,来判断是否越界,若是在动态链表中 则扩容,

//静态的链表的定义 
#define MaxSize 5//注意宏定义是没有标点的
typedef struct{
	int array[Maxsize];
	int length;
}SqList; 
//动态链表的定义
typedef struct{
	Elemtype *data;
	int lentth;//用来记录数据的长度
	int MaxSize;//用来记录数组的容量 
}SeqList;
//注意这里是申请一段空间,申请空间的方式有c风格与c++风格
//c风格 
SeqList.data=(Elemtype*)malloc(sizeof(Elemtype)*Maxsize);
//c++风格
SeqList.data= ElemType[InitSize]; 
//释放空间的时候也要注意
/*free是释放由malloc申请的空间*/ 
free(data)直接就释放了一整串的空间
delete []data;//正确使用的方法
delete data==delete data[0];//则相当于只是释放了一系列空间中的第一个空间 
data=NULL;
/*还有一个要注意的就是释放之后要将指针的指向置为NUll
因为后面要使用 就并不知道是否被释放过了*/

 

注意

插入

若是需要插入元素 ,则需要判断给出的位置是否合理,同样的也需要判断是否空间已满,若是动态已满则需要扩容,若是静态已满,退出即可,假如元素之后别忘了修改其中的Length的数据,尾插法时间复杂度是O(1) 头插法时间复杂度是O(n) 平均时间复杂度是O(n)

删除

同样的道理要是要删除,若是给定的位置信息 同样需要判断位置是否合理,需要判断其中是否有元素,并将其中的Length的长度减一,与插入相同,删除的返回值也是bool类型,与头删尾删的时间复杂度是一样的,也同样的别忘了对其中记录数据长度的Length 进行修改即可

第一题

请添加图片描述

#include<bits/stdc++.h>
#define MaxSize 5
#define ElemType int
using namespace std;
typedef struct{
	ElemType *data=NULL;
	int length=0;
	int capacity=MaxSize;
}SeqList;
bool InitSql(SeqList &L){
	L.data=(int*)malloc(sizeof(int)*MaxSize);
	cout<<"请输入你要添加的数值"<<endl;
	int input=0;int i=0;
	while(scanf("%d",&input)!=EOF){
		if(L.length==L.capacity){//需要扩容
			cout<<"此时需要扩容"<<endl;
			L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2)); 
			L.capacity*=2;
		}
		L.data[L.length++]=input;
	}
	L.length-=1;
	return true;
}
int Solution(SeqList &L){
	if(L.length==0){
		cout<<"此时链表中没有元素"<<endl; 
		return 0;
	}
	int min=L.data[0];int postion=0;
	for(int i=0;i<=L.length;i++){
		if(min>L.data[i]){
			min=L.data[i];
			postion=i;
		}
	}
	
	L.data[postion]=L.data[L.length];
}
void Print(SeqList L){
	cout<<"此时的数组是"<<endl; 
	for(int i=0;i<=L.length;i++){
		cout<<L.data[i]<<" ";
	}
}
main(){
	SeqList L;
	InitSql(L);
	Solution(L);
	Print(L); 
}

第二题

请添加图片描述

思路

就是使用两个指针 一个指向第一个 一个指向最后一个 两个指针的指向一直靠经便可

void swap(int &a,int &b){
	a^=b;
	b^=a;
	a^=b;
} 
void Solution2(SeqList &L){
	int i=0;//定义一个指针指向第一个坐标
	int j=L.length-1;//同样的定义一个指针指向最后一个元素
	while(i<j){
		swap(L.data[i++],L.data[j--]);
	}
}

第三题

请添加图片描述

思路

也是使用两个指针 一个从前往后找值为x的 一个从后向前找 值不是x的交换两个指针所指向的数值,最后若是两个相遇,判断此时指向的是否是数值为x,第二个思路就是:使用i 来遍历这个数组,使用一个k来确定每一个数移动的次数

void Solution3(SeqList &L){
	int elem;int step=0;
	cout<<"请输入你要删的值"<<endl;
	cin>>elem;
	for(int i=0;i<=L.length;i++){
		if(L.data[i]==elem){
			step++;
		}
		else L.data[i-step]=L.data[i];
	}
	L.length-=step;
}

第四题

请添加图片描述

void Solution4(SeqList &L){
		int begin;int end;int step=0;
	cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
	cin>>begin;cin>>end;
	if(L.length==0||begin>end){
		cout<<"你所输入的信息有误"<<endl; 
		return ;
	} 
	for(int i=0;i<=L.length;i++){
		if(L.data[i]>begin&&L.data[i]<end){
			step++;
		}
		else L.data[i-step]=L.data[i];
	}
	cout<<"此时的step是等于"<<step<<endl;
	L.length-=step;
}

第五题

请添加图片描述

思路

和上面的差不多,就是多了一个筛选条件

void Solution5(SeqList &L){
	int begin;int end;int step=0;
	cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
	cin>>begin;cin>>end;
	if(L.length==0||begin>end){
		cout<<"你所输入的信息有误"<<endl; 
		return ;
	} 
	for(int i=0;i<=L.length;i++){
		if(L.data[i]>=begin&&L.data[i]<=end){
			step++;
		}
		else L.data[i-step]=L.data[i];
	}
	cout<<"此时的step是等于"<<step<<endl;
	L.length-=step;
}

第六题

请添加图片描述

思路

使用快慢指针的方法,使用快指针来进行扫描数组,使用慢指针来表示慢指针之前的数都是有序的

void Solution6(SeqList &L){
	int quality=1,slow=1;
	for(int quality=1;quality<=L.length;){
		if(L.data[quality]==L.data[slow]){
			quality+=1;
		}
		else{
			slow+=1;
			L.data[slow]=L.data[quality];
			quality+=1;
		}
	}
	L.length=slow;
}

第七题

请添加图片描述

思路

我的第一想法是 使用两个指针分别指向两个数组,再开辟一个新的空间用来存储两个数组合并之后的数组,比较此时指针指向的数字的大小

SeqList* Solution7(){
	SeqList L1,L2; 
	int p=0,q=0,k=0;//定义三个指针 
	cout<<"请输入第一个数组"<<endl;
	InitSql(L1);
	cout<<"请输入第二个数组"<<endl;
	InitSql(L2);
	SeqList *L3=(SeqList*)malloc(sizeof(SeqList)*(L1.length+L2.length+2));
	for(int i=0;i<L1.length+L2.length+2;i++){
		//需要选取这么多次的数
		if(L1.data[p]<=L2.data[q]) {
			L3->data[k]=L1.data[p];
			k+=1,p+=1;	
		}
		else{
			L3->data[k]=L2.data[q];
			k+=1,q+=1;
		}
	}
	L3->length=k-1;L3->capacity=k-1;
	cout<<"此时的L3的数组是"<<endl; 
	for(int i=0;i<=L3->length;i++){
		cout<<L3->data[i]<<" ";
	}
	return L3;
}

//本来前面写的都是可执行的结果一下子一不小心给删了 就从第八题重新写一下吧,上面都是运行过的 都是可以执行的

第八题

请添加图片描述

思路

我的第一想法是,重新建立一个数组,以分界点重新将数组放入进去,但是这个想法太简单了,我们另外的想法就是首先整个数组首尾交换,交换完之后,再分别交换这两个数组的首尾的部分

void Solution8(SeqList &L){
	int border;
	cout<<"请输入一个分界线(从零开始,包括分界线也交换)"<<endl;
	cin>>border;
	int p=0,q=L.length;
	while(p<q){
		swap(L.data[p++],L.data[q--]); 
	} 
	//实现整数数组的交换 
	Print(L);
	int k=border,m=border+1;p=0,q=L.length;
	while(p<k){
		swap(L.data[p++],L.data[k--]);
	} 
	Print(L);
	while(m<q){
		swap(L.data[m++],L.data[q--]);
	}
}

第九题

请添加图片描述

思路

查找方法有许多种,这里是有序的,并且需要时间较短,这里就使用折半查找

void Solution9(SeqList &L){
	int input; 
	cout<<"请输入你要查找的值"<<endl;
	cin>>input;
	int from=0,to=L.length,mid=(L.length+0)>>2;
	while(from<=to){
		if(L.data[mid]<input){
			from=mid+1;
			mid=from+(to-from)/2;
		}
		else if(L.data[mid]>input){
			to=mid-1;
			mid=from+(to-from)/2;
		}
		else{
			cout<<"成功查找"<<endl;
			swap(L.data[mid],L.data[mid+1]);
			return ;
		}
	}
	cout<<"未存在这个数"<<endl; 
	//将mid之后的数 依次向后移动一个位置,此时就需要考虑容积什么的
	if(L.capacity==L.length+1){
		L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2)); 
		L.capacity*=2;
	} 
	int i=L.length; 
	while(i>=mid){
		L.data[i+1]=L.data[i];
		i--;
	} 
	L.data[mid]=input;
	L.length+=1;
} 

第十题

请添加图片描述

思路

你会发现几乎和上面第八题一样,你要是问我不一样之处,目前看来就题目说法不一样
时间复杂度O(n) 空间复杂度O(1)
这里就略。。。。

第11 题

请添加图片描述

思路

我的第一想法是合并两个数组,从中寻找中位数,但是这样未免太简单,若是解题的话第一种好像见两分,建议第一种方式
王道最后的答案的思想是:两个序列的中位数其实是处于两个序列各自中位数之间 ,那么此时我们在两个序列中划去两边的元素就相当于从序列C 中划去相同数量的大小元素,最后留下的也就是中位数,

int Solution11(){
	SeqList L1,L2;
	cout<<"请输入一个你要输入的一个数组"<<endl;
	InitSql(L1);
	cout<<"请输入另外一个你要输入的数组"<<endl;
	InitSql(L2);
	//找这两个数组的中位数,因为要不停的删减,这里建议使用每一个数都使用
	//两个指针,这样删除的时候改变指针的指向就可以达到同样的效果了
	int begin1=0,end1=L1.length;int begin2=0,end2=L2.length; int mid1,mid2;
	while(begin1!=end1){//当每一个顺序表包含的都是一个元素的时候
		mid1=begin1+(end1-begin1)/2;
		mid2=begin2+(end2-begin2)/2;
		if(L1.data[mid1]==L2.data[mid2]){
			cout<<"此时中位数相等 返回"<<endl; 
			return L1.data[mid1];
		}
		else if(L1.data[mid1]<L2.data[mid2]){
			cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl; 
			begin1=mid1;//舍弃L1中比L1.data[mid]小的
			end2=mid2; //舍弃L2中比L2.data[mid]大的 
		}
		else{
			cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl; 
			end1=mid1;//舍弃L1中比L1.data[mid]大的
			begin2=mid2;//舍弃L2中比L2.data[mid]小的 
		} 
	}
	//此时两个顺序表中都是只用一个元素 从中选取一个最小的放回就可以
	return L1.data[mid1]<L2.data[mid2]? L2.data[mid2]: L1.data[mid1]; 
}

运行结果

请添加图片描述

十二题

请添加图片描述

思想

我的第一个想法是,使用一个个桶来装数值,最后再来统计每一个桶中数 判断是否有一个超过n/2;
王道上给的方法是选取一个候选元素,遍历数组 若是与候选主元素相同则count++ t若是与候选主元素不同count-- 当count==0 的时候下一个出现的重新定位候选主元素,注意不能通过最后count的值来判断是否一定存在主元素 最后还需要经过一次遍历,来判断此时的候补主元素是否的确是主元素
第三个也是最简单的一个就是遍历每一个数,判断是否>n/2

void Solution12(SeqList &L){
	int count=0;int k=0;
	for(int i=0;i<=L.length;i++){
		if(L.data[i]==L.data[k]){
			count++;
		}
		else count--;
		if(0==count){
			k=i;
			count++;
		}
	}
	count=0;
	for(int i=0;i<=L.length;i++){
		if(L.data[k]==L.data[i])
		count++;
	}
	if(count>(L.length+1)/2){
		cout<<"此时数组中的主元素是"<<L.data[k]<<endl;
	}
	else cout<<"不存在主元素"<<endl;
}

13 题

请添加图片描述

思路

我的第一个思路是先进行排序,排序之后 设置一个flag 再来找是否发生改变
第二个方法相当与涂色, 设置两个数组,若是在数组中发现了数,则将flag[]=false;当一遍扫描完成再来扫描第一个出现的flag[]==true的就是最小的

void Solution13(SeqList &L){
	bool flag[L.length+3]={0};//设置这么大的空间足够,因为大于这个空间的值不必考虑,负数也不必考虑  为什么+3 因为第一个空间不用,最后一个也不用,length 本来就空间从零开始 所以加三
	for(int i=0;i<=L.length;i++){ 
		if(L.data[i]>0&&L.data[i]<=L.length+1){
			flag[L.data[i]]=true;
		}
				
	}
	
	for(int i=1;i<L.length+3;i++){
		if(!flag[i]){
			cout<<"此时的最小值是"<<i<<endl;
			return;
		}
	}
}

代码汇总

#include<bits/stdc++.h>
#define MaxSize 5
#define ElemType int
using namespace std;
typedef struct{
	ElemType *data=NULL;
	int length=0;
	int capacity=MaxSize;
}SeqList;
bool InitSql(SeqList &L){
	L.data=(int*)malloc(sizeof(int)*MaxSize);
	cout<<"请输入你要添加的数值"<<endl;
	int input=0;int i=0;
	while(scanf("%d",&input)!=EOF){
		if(L.length==L.capacity){//需要扩容
			cout<<"此时需要扩容"<<endl;
			L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2)); 
			L.capacity*=2;
		}
		L.data[L.length++]=input;
	}
	L.length-=1;
	return true;
}
int Solution1(SeqList &L){
	if(L.length==0){
		cout<<"此时链表中没有元素"<<endl; 
		return 0;
	}
	int min=L.data[0];int postion=0;
	for(int i=0;i<=L.length;i++){
		if(min>L.data[i]){
			min=L.data[i];
			postion=i;
		}
	}
	
	L.data[postion]=L.data[L.length];
}
void Print(SeqList L){
	cout<<"此时的数组是"<<endl; 
	for(int i=0;i<=L.length;i++){
		cout<<L.data[i]<<" ";
	}
	cout<<endl;
}
void swap(int &a,int &b){
	a^=b;
	b^=a;
	a^=b;
} 
void Solution2(SeqList &L){
	int i=0;//定义一个指针指向第一个坐标
	int j=L.length-1;//同样的定义一个指针指向最后一个元素
	while(i<j){
		swap(L.data[i++],L.data[j--]);
	}
}
void Solution3(SeqList &L){
	int elem;int step=0;
	cout<<"请输入你要删的值"<<endl;
	cin>>elem;
	for(int i=0;i<=L.length;i++){
		if(L.data[i]==elem){
			step++;
		}
		else L.data[i-step]=L.data[i];
	}
	L.length-=step;
}
void Solution4(SeqList &L){
		int begin;int end;int step=0;
	cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
	cin>>begin;cin>>end;
	if(L.length==0||begin>end){
		cout<<"你所输入的信息有误"<<endl; 
		return ;
	} 
	for(int i=0;i<=L.length;i++){
		if(L.data[i]>begin&&L.data[i]<end){
			step++;
		}
		else L.data[i-step]=L.data[i];
	}
	cout<<"此时的step是等于"<<step<<endl;
	L.length-=step;
}
void Solution5(SeqList &L){
	int begin;int end;int step=0;
	cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
	cin>>begin;cin>>end;
	if(L.length==0||begin>end){
		cout<<"你所输入的信息有误"<<endl; 
		return ;
	} 
	for(int i=0;i<=L.length;i++){
		if(L.data[i]>=begin&&L.data[i]<=end){
			step++;
		}
		else L.data[i-step]=L.data[i];
	}
	cout<<"此时的step是等于"<<step<<endl;
	L.length-=step;
}
void Solution6(SeqList &L){
	int quality=1,slow=1;
	for(int quality=1;quality<=L.length;){
		if(L.data[quality]==L.data[slow]){
			quality+=1;
		}
		else{
			slow+=1;
			L.data[slow]=L.data[quality];
			quality+=1;
		}
	}
	L.length=slow;
}
SeqList* Solution7(){
	SeqList L1,L2; 
	int p=0,q=0,k=0;//定义三个指针 
	cout<<"请输入第一个数组"<<endl;
	InitSql(L1);
	cout<<"请输入第二个数组"<<endl;
	InitSql(L2);
	SeqList *L3=(SeqList*)malloc(sizeof(SeqList)*(L1.length+L2.length+2));
	for(int i=0;i<L1.length+L2.length+2;i++){
		//需要选取这么多次的数
		if(L1.data[p]<=L2.data[q]) {
			L3->data[k]=L1.data[p];
			k+=1,p+=1;	
		}
		else{
			L3->data[k]=L2.data[q];
			k+=1,q+=1;
		}
	}
	L3->length=k-1;L3->capacity=k-1;
	cout<<"此时的L3的数组是"<<endl; 
	for(int i=0;i<=L3->length;i++){
		cout<<L3->data[i]<<" ";
	}
	return L3;
}
void Solution8(SeqList &L){
	int border;
	cout<<"请输入一个分界线(从零开始,包括分界线也交换)"<<endl;
	cin>>border;
	int p=0,q=L.length;
	while(p<q){
		swap(L.data[p++],L.data[q--]); 
	} 
	//实现整数数组的交换 
	Print(L);
	int k=border,m=border+1;p=0,q=L.length;
	while(p<k){
		swap(L.data[p++],L.data[k--]);
	} 
	Print(L);
	while(m<q){
		swap(L.data[m++],L.data[q--]);
	}
}
void Solution9(SeqList &L){
	int input; 
	cout<<"请输入你要查找的值"<<endl;
	cin>>input;
	int from=0,to=L.length,mid=(L.length+0)>>2;
	while(from<=to){
		if(L.data[mid]<input){
			from=mid+1;
			mid=from+(to-from)/2;
		}
		else if(L.data[mid]>input){
			to=mid-1;
			mid=from+(to-from)/2;
		}
		else{
			cout<<"成功查找"<<endl;
			swap(L.data[mid],L.data[mid+1]);
			return ;
		}
	}
	cout<<"未存在这个数"<<endl; 
	//将mid之后的数 依次向后移动一个位置,此时就需要考虑容积什么的
	if(L.capacity==L.length+1){
		L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2)); 
		L.capacity*=2;
	} 
	int i=L.length; 
	while(i>=mid){
		L.data[i+1]=L.data[i];
		i--;
	} 
	L.data[mid]=input;
	L.length+=1;
} 
int Solution11(){
	SeqList L1,L2;
	cout<<"请输入一个你要输入的一个数组"<<endl;
	InitSql(L1);
	cout<<"请输入另外一个你要输入的数组"<<endl;
	InitSql(L2);
	//找这两个数组的中位数,因为要不停的删减,这里建议使用每一个数都使用
	//两个指针,这样删除的时候改变指针的指向就可以达到同样的效果了
	int begin1=0,end1=L1.length;int begin2=0,end2=L2.length; int mid1,mid2;
	while(begin1!=end1){//当每一个顺序表包含的都是一个元素的时候
		mid1=begin1+(end1-begin1)/2;
		mid2=begin2+(end2-begin2)/2;
		if(L1.data[mid1]==L2.data[mid2]){
			cout<<"此时中位数相等 返回"<<endl; 
			return L1.data[mid1];
		}
		else if(L1.data[mid1]<L2.data[mid2]){
			cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl; 
			begin1=mid1;//舍弃L1中比L1.data[mid]小的
			end2=mid2; //舍弃L2中比L2.data[mid]大的 
		}
		else{
			cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl; 
			end1=mid1;//舍弃L1中比L1.data[mid]大的
			begin2=mid2;//舍弃L2中比L2.data[mid]小的 
		} 
	}
	//此时两个顺序表中都是只用一个元素 从中选取一个最小的放回就可以
	return L1.data[mid1]<L2.data[mid2]? L2.data[mid2]: L1.data[mid1]; 
}
void Solution12(SeqList &L){
	int count=0;int k=0;
	for(int i=0;i<=L.length;i++){
		if(L.data[i]==L.data[k]){
			count++;
		}
		else count--;
		if(0==count){
			k=i;
			count++;
		}
	}
	count=0;
	for(int i=0;i<=L.length;i++){
		if(L.data[k]==L.data[i])
		count++;
	}
	if(count>(L.length+1)/2){
		cout<<"此时数组中的主元素是"<<L.data[k]<<endl;
	}
	else cout<<"不存在主元素"<<endl;
}
void Solution13(SeqList &L){
	bool flag[L.length+3]={0};//设置这么大的空间足够,因为大于这个空间的值不必考虑,复数也不必考虑 
	for(int i=0;i<=L.length;i++){ 
		if(L.data[i]>0&&L.data[i]<=L.length+1){
			flag[L.data[i]]=true;
		}
				
	}
	
	for(int i=1;i<L.length+3;i++){
		if(!flag[i]){
			cout<<"此时的最小值是"<<i<<endl;
			return;
		}
	}
}
void Menu(){
	int choice;
	cout<<"请问你要解决第几题";
	cin>>choice;
	switch(choice){
		case 1:{
			SeqList L;
			InitSql(L);
			Solution1(L);
			Print(L);
			break;
		}
		case 2:{
			SeqList L;
			InitSql(L);
			Solution2(L);
			Print(L);
			break;
		}
		case 3:{
			SeqList L;
			InitSql(L);
			Solution3(L);
			Print(L);			
			break;
		}
		case 4:{
			SeqList L;
			InitSql(L);
			Solution4(L);
			Print(L);			
			break;
		}
		case 5:{
			SeqList L;
			InitSql(L);
			Solution5(L);
			Print(L);			
			break;
		}
		case 6:{
			SeqList L;
			InitSql(L);
			Solution6(L);
			Print(L);			
			break;
		}
		case 7:{
			Solution7();
			break;
		}
		case 8:{
			SeqList L;
			InitSql(L);
			Solution8(L);
			Print(L);
			break;
		}
		case 9:{
			SeqList L;
			InitSql(L);
			Solution9(L);
			Print(L);			
			break;
		}
		case 10:{
			SeqList L;
			InitSql(L);
			Solution8(L);
			Print(L);
			break;
		}
		case 11:{
			cout<<"此时序列的中位数是"<<Solution11()<<endl;
			break;
		}
		case 12:{
			SeqList L;
			InitSql(L);
			Solution12(L);			
			break;
		}
		case 13:{
			SeqList L;
			InitSql(L);
			Solution13(L);				
			break;
		}
		default: break;
	}
}
main(){
	Menu();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值