#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(){
}