DS数据结构_线性表_(1)基本操作

#include <iostream>
#include<stdio.h>
#include <cstdlib>
#define MaxSize 50
#define InitSize 40
#define ElemType int
#define INPUT 1
#define DEFAULT 2
#define NULLLIST 0

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;

//定义结构类型
//固定长度线性表
typedef struct {
	ElemType data[MaxSize];
	int lentgh;//从1开始
}SqListSta;
//可变长度线性表
typedef struct {
	ElemType *data;
	int length;//从1开始
}SqList;


/**
	接下来的基本操作全部使用可变长度线性表实现
**/

//初始化函数
bool initSqList(SqList &L , int initType);

//线性表中插入
bool ListInsert(SqList &L,int loc ,ElemType e);

//线性表删除
bool ListDelete(SqList &L,int loc ,ElemType &e);

//线性表查找
int LocateElem(SqList &L,ElemType e);

//输出线性表
bool ShowList(SqList L);

//question1 :从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删除的元素,空出的位置由最后一个元素填补
bool question1(SqList &L,ElemType &e);

//question2 :设计一个高效算法,将顺序表L的所有元素逆置,空间复杂度要求为O(1)
bool question2(SqList &L);

//question3 :时间复杂度O(n),空间复杂度O(1),删除鄋值为x的元素
bool question3_1(SqList &L,ElemType e);
bool question3_2(SqList &L,ElemType e);

//question5 :从顺序表中删除值在 s,t之间的所有元素,要求检查s,t正确性
bool question5(SqList &L,ElemType s,ElemType t);

//question6 : 删除所有重复元素
bool question6(SqList &L);

//question7 :两个有序表合并新的有序表
bool question7(SqList &L1 ,SqList &L2,SqList &L3);

//question8 :将顺序表中前后两部分互换
bool reverse(SqList &L,int left , int right);
bool question8(SqList &L, int left , int mid , int right);

//question9 :有序线性表重尽快的查找x位置,找到则与后面元素位置互换。
bool question9(SqList L , ElemType x , int left , int right);
 
//question10:  将线性表中的s到t位置的元素循环左移p个位置,尽可能高效
bool question10(SqList &L, int s ,int t ,int p);

/*question11:升序列表S长度为L,在L/2向上取整位置为中位数,两个序列的中位数是所有元素升序的中位数
	两个等长升序序列,高效算法找出两个序列的中位数
*/
bool question11(SqList &L1, SqList &L2, ElemType &e);

/*question12:序列中有大于L/2个元素等于x,则x为该序列主元素
	高效找出主元素。
*/
bool question12(SqList &L , ElemType &mainElem);


/*
	主函数
*/
int main(int argc, char** argv) {
	int selection;
	SqList L;
	initSqList(L,DEFAULT);


	while(true){
		cout<<"\n---------请输入功能---------\n"<<endl ;
		cout<<"0.退出\t"<<"1.查看线性表\t"<<"2.插入\t"<<"3.删除\t"<<"4.查找"<<endl;
		cout<<"5. question1 :从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删除的元素,空出的位置由最后一个元素填补\n";
		cout<<"6. question2 :设计一个高效算法,将顺序表L的所有元素逆置,空间复杂度要求为O(1)\n";
		cout<<"7. question3 :时间复杂度O(n),空间复杂度O(1),删除鄋值为x的元素\n";
		cout<<"8. question5 :从顺序表中删除值在 s,t之间的所有元素,要求检查s,t正确性\n"; 
		cout<<"9. question6 : 删除所有重复元素\n";
		cout<<"10. question7 :两个有序表合并新的有序表\n";
		cout<<"11. question8 :将顺序表中前后两部分互换\n";
		cout<<"12. question10:  将线性表中的s到t位置的元素循环左移p个位置,尽可能高效\n";
		cout<<"13. question11:升序列表S长度为L,在L/2向上取整位置为中位数,两个序列的中位数是所有元素升序的中位数两个等长升序序列,高效算法找出两个序列的中位数\n";
        cout<<"14. question12:序列中有大于L/2个元素等于x,则x为该序列主元素 高效找出主元素。\n\n";

		cin>>selection;

		switch(selection){
			case 0:{
				exit(1);
				break;
			}
			// 1.查看线性表
			case 1:{
				ShowList(L);
				break;
			}
			// 2.插入
			case 2:{
				cout<<"\n-------输入位置和插入值-------\n";
				int loc;
				ElemType elem;
				cin>>loc>>elem;
				if(!ListInsert(L,loc,elem))
					cout<<"  ERROR!";
				ShowList(L);
				break;
			}
			// 3.删除
			case 3:{
				cout<<"\n--------输入删除位置--------\n" ;
				int loc;
				int e;
				cin>>loc;
				if(!ListDelete(L,loc,e))
					cout<<"ERROR!";
				ShowList(L);
				break;
			}
			// 4.查找
			case 4:{
				cout<<"\n--------输入查找的值--------\n" ;
				int e;
				cin>>e;
				int loc = LocateElem(L,e);
				if(loc == -1)
					cout<<"ERROR!";
				else
					cout<<loc;
				ShowList(L);
				break;
			}
			//question1 :从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删除的元素,空出的位置由最后一个元素填补
			case 5:{
				ElemType e;
                question1(L,e);
                cout<<"删除最小元素为:"<<e ;
				break;
			}
			//question2 :设计一个高效算法,将顺序表L的所有元素逆置,空间复杂度要求为O(1)\n
			case 6:{
				question2(L);
				break;
			}
			//question3 :时间复杂度O(n),空间复杂度O(1),删除鄋值为x的元素\n
			case 7:{
				ElemType e;
				cout<<"输入要删除的元素\n";
				cin>>e; 
				question3_1(L,e);
				break;
			}
			//question5 :从顺序表中删除值在 s,t之间的所有元素,要求检查s,t正确性\n
			case 8:{
				int s , t;
				cout<<"输入范围s,t\n";
				cin>>s>>t; 
				question5(L,s,t);
				break;
			}
			//question6 : 删除所有重复元素\n
			case 9:{
			
				question6(L);
				break;
			}
			//question7 :两个有序表合并新的有序表\n
			case 10:{
				//****??????
				SqList L1;
				SqList L2;
				SqList L3;
				initSqList(L3,NULLLIST);
				cout<<"输入第一个顺序表:\n";
				initSqList(L1,INPUT);
				cout<<"输入第二个顺序表:\n";
				initSqList(L2,INPUT); 
				ShowList(L1);
				ShowList(L2);
				question7(L1,L2,L3);
				ShowList(L3); 
				break;
			}
			// question8 :将顺序表中前后两部分互换\n
			case 11:{
				int left,right,mid; 
				cout<<"输入互换部分首位置\n";
				cin>>left;
				cout<<"输入互换位置中间位置\n";
				cin>>mid;
				cout<<"输入互换位置尾位置\n";
				cin>>right; 
				question8(L,left ,mid ,right);
				break;
			}
			//question10:  将线性表中的s到t位置的元素循环左移p个位置,尽可能高效\n
			case 12:{
				int left,right,p; 
				cout<<"输入互换部分首位置\n";
				cin>>left;
				cout<<"输入互换位置中间位置\n";
				cin>>p;
				cout<<"输入互换位置尾位置\n";
				cin>>right; 
				question10(L,left,right,p); 
				break;
			}
			// question11:升序列表S长度为L,在L/2向上取整位置为中位数,两个序列的中位数是所有元素升序的中位数两个等长升序序列,高效算法找出两个序列的中位数\n
			case 13:{
				SqList L1;
				SqList L2;
				ElemType e;
				cout<<"输入升序列表1:\n";
				initSqList(L1,INPUT);
				cout<<"输入升序列表2:\n";
				initSqList(L2,INPUT);
				question11(L1,L2,e);
				cout<<"中位数为:"<<e <<endl;
				break;
			}
			//question12:序列中有大于L/2个元素等于x,则x为该序列主元素 高效找出主元素。
			case 14:{
				
				break;
			}
			//
			case 15:{

				break;
			}
			//
			case 16:{

				break;
			}
		}
	}



	return 0;
}
/**

**/



//初始化动态线性表空间
/**
	initType : 新建线性表的方式 
**/ 
bool initSqList(SqList &L,int initType){
	
	//控制台输入线性表内容 
	if(initType == 1){
		L.data = new ElemType[MaxSize];
		cout<<"\n新建顺序表,请输入长度,内容,空格隔开\n";
		int len;
		cin>>len; 
		L.length = len;
		for(int i=0;i<len;i++){
			cin>>L.data[i];
		}
		ShowList(L);
	}else if(initType == 2){
		//使用默认创建线性表 
		L.data = new ElemType[InitSize];
		L.length = 10;
		for(int i=0;i<10;i++){
  	    L.data[i] = i+1;
		}
		ShowList(L);
	} else if(initType == 0){
		L.data = new ElemType[MaxSize];
		L.length =0;
	
	}
	
	cout<<"---------新建完成---------\n"; 

}

//显示线性表全部内容
bool ShowList(SqList L){
	cout<<"\n----------showList----------"<<endl;
	for(int i=0;i< L.length;i++){
		cout<<L.data[i]<<" ";
	}
	cout<<"length: "<<L.length<<endl; 

}

//线性表中插入
/**
	loc :表中位置为 1 <= i <= length+1
	e : 插入的数据 
**/
bool ListInsert(SqList &L,int loc,ElemType e){
	//如果长度小于0或者大于最大长度则报错
	if(loc>L.length+1 || loc<1){
		return false;
	}else{
		// 从后往前扫描
		// 初始位置为 length 而不是length-1 ,为给新插入数据的空间,所有元素后移一位 
		for(int j=L.length ; j>=loc ; j--){
			L.data[j] = L.data[j-1];
		}
		L.data[loc-1] = e;
		L.length+=1; //长度+1
	}
	return true;
}


//线性表删除  将删除的数据通过e返回
//根据位置进行删除
/**
	loc : 删除值的位置
	e : 返回删除的值 
**/ 
bool ListDelete(SqList &L,int loc ,ElemType &e){
	 if(loc< 1 || loc > L.length+1){
	 	return false;
	 }else{
	 	// 保存该位置的值 
	 	e = L.data[loc-1];
		//所有元素前移 
		for(int j=loc-1 ; j<L.length ; j++){
			L.data[j] = L.data[j+1];
		}
		L.length-=1;//长度减一
	 }
	return true;
}


//线性表按值查找
int LocateElem(SqList &L,ElemType e){
	for(int i=0 ; i<L.length ; i++) {
		if(L.data[i] == e){
			return i+1; //返回该值的位置 ,下表+1
		}
	}

	return -1;//未找到元素,返回-1
}


//交换两元素位置
//下表为参数
/**
	loc1 : 第一个元素位置
	loc2 : 第二个元素位置 
**/ 
bool swap(SqList &L,int loc1,int loc2){
	if(loc1<0||loc2>L.length){
		return false;
	}
	ElemType e;
	e = L.data[loc1];
	L.data[loc1] = L.data[loc2];
	L.data[loc2] = e;
	return true;
}

//question1 :从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删除的元素,空出的位置由最后一个元素填补
bool question1(SqList &L,ElemType &e){
	int min = 999999;//放置线性表为空
	int flag = -1; //定位查找到的元素的位置 
	// 查找最小值的位置 
	for(int i=0;i<L.length;i++){
		if(min >= L.data[i]){
			min =  L.data[i];
			flag = i ;
		}
	}
	//根据flag确定是否找到最小值,(表是否为空) 
	if(flag!=-1){
		e = min;
		L.data[flag] = L.data[L.length-1];
		L.length-=1;
	}else{
		return false;
	}
	return true;

}

//question2 :设计一个高效算法,将顺序表L的所有元素逆置,空间复杂度要求为O(1)
bool question2(SqList &L){
	 
	for(int i=0;i<L.length/2;i++){
		swap(L,i,L.length-i-1);
	}
	return true;
}

//question3 :时间复杂度O(n),空间复杂度O(1),删除所有值为x的元素
bool question3_1(SqList &L,ElemType e){
	//算法思路
	//计数记住该序列中有k个不为x的数字,将每一个不为x的数组放到序列的k个位置 
	int k =0;
	for(int i=0;i<L.length;i++){
		if(L.data[i] != e){
			L.data[k] = L.data[i];
			k++;
		}
	}
	L.length = k;
	return true;
}

bool question3_2(SqList &L,ElemType e){
	//算法思路
	//计数有k个为x的数字,遇到不为x的数字吧该数字放到length-k 位置上
	int k=0;
	for(int i=0;i<L.length;i++){
		if(L.data[i] == e){
			k ++;
		}
		else{
			//!!!!!易错 
			L.data[i-k] = L.data[i];
		}
	} 
	L.length = L.length -k;
	return true;
} 

//question5 :从顺序表中删除值在 s,t之间的所有元素,要求检查s,t正确性
bool question5(SqList &L,ElemType s ,ElemType t){
	if(s > t){
		return false;
	} 
	int num = 0;//记录不是 s , t 范围之间只数字个数 
	
	for(int i=0 ; i < L.length;i++){
		//不是范围之内的全部放到对应位置上
		//范围之内的直接略过,不进行存储。 
		if(L.data[i] > t || L.data[i] < s){
			L.data[num] = L.data[i];
			num++;
		}
		
	}
}

//question6 : 删除所有重复元素
bool question6(SqList &L){
	ElemType e;
	for( int i=0 ; i<L.length ; i++){
		for(int j=i +1 ; j<L.length ; j++){
			if(L.data[i] == L.data[j]){
				ListDelete(L,i+1,e);
			}
		}
	} 
	
}

//question7 :两个有序表合并新的有序表
//这里新建一个顺序表用于存储新的有序表 
bool question7(SqList &L1 , SqList &L2,SqList &L3){
	int f1 = 0;
	int f2 = 0;
	int f3 = 0;
	while(f1<L1.length && f2 < L2.length){
		if(L1.data[f1]<L2.data[f2]){
			L3.data[f3++] = L1.data[f1++];
			L3.length++;
		//	f3++;
		//	f1++;
		}else if(L1.data[f1] > L2.data[f2]){
			L3.data[f3++] = L2.data[f2++];
			L3.length++;
		//	f3++;
		//	f2++;
		} else{
			L3.data[f3++] = L1.data[f1++];
			L3.length++;
		//	f3++;
		//	f1++;
			L3.data[f3++] = L2.data[f2++];
			L3.length++;
		//	f3++;
		//	f2++;
		} 
	}
	if(f1 == L1.length){
		for(int j = f2; j<L2.length ; j++){
			L3.data[f3++] = L2.data[j];
			L3.length++;
			
		}
	}else{
		for( int j = f1; j<L1.length ;j++){
			L3.data[f3++]  = L1.data[j];
			L3.length++;
		}
	}
	return true;
}

//question8 :将顺序表中前后两部分互换
//转置两段全部,转置前段, 转置后段 
bool reverse(SqList &L,int left , int right){
	for(int i=left - 1 ; i< (left+right)/2 ;i++){
		swap(L, i , right - 1);
	}
	return true;
} 
bool question8(SqList &L, int left , int mid , int right){
	reverse(L, left , right);
	reverse(L, left , mid);
	reverse(L, mid, right);
}

//question9 :有序线性表重尽快的查找x位置,找到则与后面元素位置互换。
/**
	二分查找 
	left 为要查找段的左位置
	right 为右位置 
	
**/
bool question9(SqList L , ElemType x , int left , int right){
	
	int mid = (left + right) / 2 ;
	if(L.data[mid] == x){
		swap(L,mid,mid+1);
		return true; 
	}else if(L.data[mid] > x){
		question9(L , x , left , mid);
	}else if(L.data[mid] < x){
		question9(L , x ,mid ,right);
	}
}

//question10:  将线性表中的s到t位置的元素循环左移p个位置,尽可能高效
bool question10(SqList &L, int s ,int t ,int p){
	reverse(L,s , t);
	reverse(L, s , s+p);
	reverse(L, s+p , t);
}

/*question11:升序列表S长度为L,在L/2向上取整位置为中位数,两个序列的中位数是所有元素升序的中位数
	两个等长升序序列,高效算法找出两个序列的中位数
*/
bool question11(SqList &L1, SqList &L2, ElemType &e){
	/**
		A,B的中位数为a,b
		a = b 即a或者b为中位数
		a < b 舍弃A中较小的一版,同时舍弃B中较大的一半
		a > b 舍弃A中较大的一半,同时舍弃B中较小的一半
		重复此过程,直到只剩一个元素 
	**/
	int n = L1.length;
	int s1 = 0;
	int d1 = n - 1;
	int m1;
	int s2 = 0;
	int d2 = n-1;
	int m2;
	//分别表示序列A和序列B的首位数, 末尾数,中位数
	while(s1 != d1 || s2 != d2){
		m1 = ( s1 + d1 ) /2;
		m2 = ( s2 + d2 ) /2;
		if( L1.data[m1]  == L2.data[m2]){
			return L1.data[m1];
		} 
		if(L1.data[m1] < L2.data[m2]){
			if( ( s1 + d1) % 2  == 0 ){
				s1 = m1;
				d2 = m2;
			}
			else{
				s1 = m1 + 1;
				d2 = m2;
			}
		}
		else{
			if((s2 + d2)%2 == 0){
				d1 = m1;
				s2 = m2;
			}else{
				d1 = m1;
				s2 = m2+1;
			}
		}
	} 
	e = L1.data[s1] < L2.data[s2] ? L1.data[s1] : L2.data[s2];
}

/*question12:序列中有大于L/2个元素等于x,则x为该序列主元素
	高效找出主元素。
*/
bool question12(){
	
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值