【数据结构】顺序表王道综合题

首先是大概的一个框架,然后重点说的是第12题。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
typedef struct LNode{
	int data[100];
	int length;
}SqList;

int n,m;
void InitList(SqList &L){						//构造顺序表 
	int i;
	cin >> n;
	for(i=0;i<n;i++)
		cin >> L.data[i];
	L.length=n;
}
void Trave(SqList &L){							//遍历顺序表 
	int i;
	for(i=0;i<L.length;i++)
		cout << L.data[i] << " ";
	cout << endl;
	cout << "The Length is "<< L.length <<endl;
} 
void Reverse(SqList &L,int left,int right){		//逆置函数 ,从left处到right处的逆置
	int i,num;
	for(i=left;i<=(right-left)/2;i++){
		num=L.data[right-i];
		L.data[right-i]=L.data[i];
		L.data[i]=num;
	}
	return ;
}

int main()
{
	SqList L;
	SqList La,Lb;
	while(true){
		InitList(L);
		//Trave(L);
		//InitList(La);
		//Trave(La);
		//f6(L);
		//f7(L,La);
		//Lb=f7(L,La);
		//Trave(Lb);
		//f8(L);
		//Trave(L);
		//f9(L,9);
		//f12(L); 
		//cout << f12(L) << endl;
		Trave(L);	
	}
	return 0;
}

下面是一些题目的函数:

void f6(SqList &L){						//删除有序表中的重复元素 
	int i,k=0;
	for(i=1;i<L.length;i++){
		if(L.data[k]!=L.data[i]){
			k++;
			L.data[k]=L.data[i];
		}
	}
	L.length=k+1;
}
SqList f7(SqList &La,SqList &Lb){		//合并两个有序表 
	SqList L;
	int i,j,k=0;
	for(i=0,j=0;i<La.length,j<Lb.length;){
		if(La.data[i]>=Lb.data[j]){
			L.data[k++]=Lb.data[j];
			j++;
		}
		else if(La.data[i]<Lb.data[j]){
			L.data[k++]=La.data[i];
			i++;
		}
	}
	if(i<La.length){
		for(;i<La.length;i++){
			L.data[k++]=La.data[i];
		}
	}
	else if(j<Lb.length){
		for(;j<Lb.length;j++){
			L.data[k++]=Lb.data[j];
		}
	}
	L.length=k;
	return L;
}
void f8(SqList &L){			//顺序表L=(La,Lb)处理后L=(Lb,La) 
	int n,m;
	cin >> n >> m;
	Reverse(L,0,n+m-1);
	//Trave(L);
	Reverse(L,0,n-1);
	Reverse(L,n,n+m-1);
} 
void f9(SqList &L,int x){			//O(n) 查找元素x然后与后面节点交换数值
	int i,j,k=0;					//找不到的时候插入到有序表中
	for(i=0;i<L.length;i++){
		if(L.data[i]==x&&i!=L.length-1){
			L.data[i]=L.data[i+1];
			L.data[i+1]=x;
			return ;
		}
		if(L.data[i]>x){
			for(j=L.length;j>i;j--)
				L.data[j]=L.data[j-1];
			L.data[j]=x;
			L.length++;
			return ;
		}
	}
} 
int f11(SqList &La,SqList &Lb,int n){	//找到两个升序列合并之后的中位数 
	int s1=0,d1=n-1,m1;
	int s2=0,d2=n-1,m2;
	while(s1!=d1||s2!=d2){			//时间复杂度O(log2n)
		m1=(s1+d1)/2;
		m2=(s2+d2)/2;
		if(La.data[m1]==Lb.data[m2])			//两个序列的中位数相等的时候直接退出 
			return La.data[m1];
		if(La.data[m1]>Lb.data[m2]){			//主要是二分的思想逐渐折半然后比较
			if((s1+d1)%2==0){
				s1=m1;
				d2=m2;
			}
			else{
				s1=m1+1;
				d2=m2;
			}
		}
		if(La.data[m1]<Lb.data[m2]){
			if((s2+d2)%2==0){
				d1=m1;
				s2=m2;
			}
			else{
				d1=m1;
				s2=m2+1;
			}
		}
	}
	return La.data[s1]<Lb.data[s2]?La.data[s1]:Lb.data[s2];
} 

第12题:【2013年统考题】找到到顺序表中的主元素,主元素的定义为出现的次数m>n/2,其中n是整个表的长度。
思考:
这个题目我最先想的是统计各个整数出现的个数,找到出现次数最多的数就时候选主元素。统计的话需要占用空间O(n),时间上只要跑两遍就可以了,第一遍统计第二遍比较多少,时间复杂度也是O(n)。但是参考答案只需要O(1)的空间复杂度,就是直接找候选主元素。
思路:
首先设置第一个元素为候选主元素,这个毋庸置疑。然后从第二个元素开始往后比较,相同的话计数count++;不相同的话count–;这里也好懂。**重点 **是当目前的元素与候选主元素不相同的时候,如果count<=0,说明了当前的候选主元素已经个数为0了,就是说每出现一次这个数(假设是num),都会有另外一个不相等的数进行抵消,num到目前的进度的时候达不到1/2.所以这个时候就必须要更换种子选手了,既然能当上种子选手也说明他在前面的序列中,出现的个数也是相当的多了,不然就会有其他的种子选手替换掉他。所以这时候就换下一个选手作为种子选手了。
当count<=0时,更换了种子选手,那么换掉的下一个种子选手可能还没有换之前的多怎么办呢。这个换个角度就能想明白了,既然作为一名种子选手就是想成为主元素的,那么主元素要求就是count>n/2,这就说明,走到最后的时候他能干掉所有其他的种子选手,是就是每出现一个不一样的元素,都能找一个元素给抵消掉,不管小伙伴来的有多晚,都能抵消掉。
看两组样例:
在这里插入图片描述
无论中间的时候种子选手会换给谁当,只要你是主元素,你都能给他们比下去,有这就够了。

int f12(SqList &L){				//找到出现次数大于length/2的元素 
	int i,num;
	int count=1;
	num=L.data[0];				//设置候选主元素为第一个 
	for(i=1;i<L.length;i++){	//查找候选主元素 
		if(L.data[i]==num)
			count++;			//与候选主元素相同则计数+1 
		else{
			if(count>0)			//计数count>0说明当前候选主元素不低于1/2 
				count--;
			else{				//count<0则需要更换候选主元素 
				num=L.data[i];
				count=1;
			}
		}
		cout << i << ":" << count << " " << num << endl;
	}
	if(count>0){					
		count=0;
		for(i=0;i<L.length;i++){	//统计实际出现的次数 
			if(L.data[i]==num)
				count++;
		}
	}
	if(count>L.length/2)
		return num;
	else
		return -1;
}
int  f13(SqList &L){			//时间复杂度O(n),空间:O(n)
	int k=0;
	int  a[n+2];
	int  i;
	memset(a,0,sizeof(a));
	for(i=0;i<L.length;i++){	//找到最小的未出现的正整数
		a[L.data[i]]++;
	}
	for(i=1;i<=n+1;i++){
		if(a[i]==0)
			return i;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章