实验2、基于顺序表的非递减有序表的合并
(1)实验目的
通过该实验,深入理解顺序表的逻辑结构、物理结构等概念,掌握顺序表基本操作的编程实现,注意顺序表插入、删除等操作过程中数据元素的移动现象,培养学生编写程序时,要考虑程序的健壮性,全面考虑问题,熟练掌握通过函数参数返回函数结果的办法。
(2)实验内容
编程实现顺序表下教材第二章定义的线性表的基本操作,并根据已经实现的基本操作(函数),通过调用函数,实现两个非递减有序的线性表的合并,注意,合并时,如果有重复的元素(一个表内部的重复元素和两个表之间的重复元素),请保留一个。
(3)实验要求
(a)求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值;(b)为了方便修改数据元素的类型,请使用类型重定义,可以方便修改线性表中的数据元素的类型;(c)大部分函数的返回结果应是函数执行是否成功的一种状态,执行成功了,才返回具体的结果值;(d)对每个功能进行测试时,要求把不合法的情况也测试一下。
#include<iostream>
#include<cstdlib>//exit函数
using namespace std;
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
#define OVERFLOW -1 //为exit()定义常量
int a_ok=0; //全局变量,判断空间申请是否成功
int b_ok=0; //申请成功
typedef int ElemType;
typedef struct{
ElemType *elem; //存储空间基址 规定ElemType的默认是int型
int length; //当前长度
int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList;
//1 初始化线性表
void InitList_Sq(SqList &L){
L.elem=(ElemType*)malloc(LIST_INIT_SIZE *sizeof(ElemType));
/*
分配内存空间函数malloc:(类型说明符*)malloc(size)
(类型说明符*)表示把返回值强制转换为该类型指针。
“类型说明符”表示把该区域用于何种数据类型。
*/
if(!L.elem){
cout<<"初始化空间失败,请重新操作"<<endl;
exit(OVERFLOW);// 当程序运算出现上溢时,退出程序并报错给主调进程
}
L.length=0; //表长
L.listsize=LIST_INIT_SIZE; //分配存储容量
cout<<"储存空间分配成功"<<endl;
}
//2 销毁线性表
void Destroylist_Sq(SqList &L){
free(L.elem);
/*
free(void*ptr);
功能:释放ptr所指向的一块内存空间,
ptr是一个任意类型的指针变量,
它指向被释放区域的首地址。
被释放区应是由malloc或calloc函数所分配的区域。
*/
L.elem=NULL;
if(!L.elem){
cout<<"销毁成功";
}
else {
cout<<"销毁失败";
exit(0);// 正常退出,若exit(x),x!=0,则为异常输出
}
cout<<endl;
}
//3 清空线性表
void ClearList_Sq(SqList &L){
L.length=0;
L.listsize=LIST_INIT_SIZE; //重新分配存储容量
cout<<"清空成功";
}
//4 判断线性表是否为空
void EmptyList_Sq(SqList &L){
if(L.length==0){
cout<<"该线性表是空表" ;
}
else cout<<"不是空表";
cout<<endl;
}
//5 求线性表的长度
void GetLength_Sq(SqList &L){
cout<<"表长为"<<L.length<<endl;
}
//6 求指定位置元素的值
void GetElem_Sq(SqList &L){
int index; //元素的位置
cout<<"该表的长度为:"<<L.length<<endl;
cout<<"请输入你想查询的元素位置:";
cin>>index;
if(index>0&&index<L.length+1){
cout<<"你查询的元素为:"<<L.elem[index-1]<<endl;
}
else cout<<"你输入的位置超出了表a的范围.";
cout<<endl<<endl;
}
//7 根据元素的值来获取位置
void GetIndex_Sq(SqList &L){
int g_elem;//元素的值
int index=0;
cout<<"请输入你要查询的元素:";
cin>>g_elem;
for(int i=0;i<L.length;i++){
if(g_elem==L.elem[i]){
index=i+1;
cout<<"该元素所在位置为:"<<index<<endl;
return;//退出程序
}
}
cout<<"该表中不存在该元素.";
cout<<endl;
}
//8 求前驱
void PriorElem_Sq(SqList &L){
int index;
cout<<"请输入线性表a中某一元素的位置:(范围:2~"<<L.length<<")"<<endl;
cin>>index;
if(index<L.length+1&&index>1){ //首位无前驱
cout<<"该位置的前驱是:"<<L.elem[index-2]<<endl;
cout<<endl;
}
else cout<<"输入有误!该位置无前驱或者该元素不存在!"<<endl;
}
//9 求后驱
void NextElem_Sq(SqList &L){
int index;
cout<<"请输入线性表a中某一元素的位置:(范围:1~"<<L.length-1<<")"<<endl;
cin>>index;
if(index<L.length&&index>0) { //末位无后驱
cout<<"该位置的后驱是:"<<L.elem[index]<<endl;
cout<<endl;
}
else cout<<"输入有误!该位置无后驱或者该元素不存在!"<<endl;
}
//10 在指定位置前插入元素
void ListInsert(SqList &L1,SqList &L2){
if(a_ok==0&&b_ok==0){
cout<<"线性表a或b未能初始化!请重新输入!"<<endl;
}
else{
int index=0;
int i_elem=0;
int which=0;
cout<<"请输入你要插入的线性表的序号:"<<endl;
cout<<"1.线性表a."<<endl;
cout<<"2.线性表b."<<endl;
cin>>which;
if(which==1){
cout<<"请输入要插入的位置:(范围:1~"<<L1.length+1<<")"<<endl;
cin>>index;
cout<<"请输入你要插入的元素值:";
cin>>i_elem;
if(index<1||index>L1.length+1){
cout<<"位置越界!插入失败!"<<endl;
return;
}
else{
int *q=&(L1.elem[index-1]);
for(int *p=&(L1.elem[L1.length-1]);p>=q;--p){
*(p+1)=*p;
}
*q=i_elem;
++L1.length;
cout<<"插入成功!"<<endl;
}
}
else if(which==2){
cout<<"请输入要插入的位置:(范围:1~"<<L2.length+1<<")"<<endl;
cin>>index;
cout<<"请输入你要插入的元素值:";
cin>>i_elem;
if(index<1||index>L2.length+1){
cout<<"位置越界!插入失败!"<<endl;
return;
}
else{
int *q=&(L2.elem[index-1]);
for(int *p=&(L2.elem[L2.length-1]);p>=q;--p){
*(p+1)=*p;
}
*q=i_elem;
++L2.length;
cout<<"插入成功!"<<endl;
}
}
else cout<<"输入有误!请重新输入!";
}
}
//11 删除线性表指定位置的元素
void ListDelete(SqList &L1,SqList &L2){
if(a_ok==0&&b_ok==0){
cout<<"线性表a或b未能初始化!请重新输入!"<<endl;
}
else{
int index=0;
int dl_elem=0;
int which=0;
cout<<"请输入你要删除的线性表的序号:"<<endl;
cout<<"1.线性表a."<<endl;
cout<<"2.线性表b."<<endl;
cin>>which;
if(which==1){
cout<<"请输入你要删除的元素的位置:(范围:1~"<<L1.length<<")"<<endl;
cin>>index;
if(index<1&&index>L1.length){
cout<<"位置越界!删除失败!"<<endl;
}
else{
int *q=&(L1.elem[index-1]);
for(int *p=&(L1.elem[L1.length-1]);q<p;++q){
*q=*(q+1);
}
--L1.length;
cout<<"删除元素成功!"<<endl;
}
}
else if(which==2){
cout<<"请输入你要删除的元素的位置:(范围:1~"<<L2.length<<")"<<endl;
cin>>index;
if(index<1&&index>L2.length){
cout<<"位置越界!删除失败!"<<endl;
}
else{
int *q=&(L2.elem[index-1]);
for(int *p=&(L2.elem[L2.length-1]);q<p;++q){
*q=*(q+1);
}
--L2.length;
cout<<"删除元素成功!"<<endl;
}
}
else cout<<"输错了!请重新输入!"<<endl;
}
}
//12 显示线性表
void ListPrint_Sq(SqList &L){
cout<<"该线性表打印为"<<endl;
for(int i=0;i<L.length;i++){
cout<<L.elem[i]<<" "<<endl;
}
}
//13 合并两个非递减的线性表
void ListHebing(SqList &L1,SqList &L2,SqList &L3){
if(a_ok==0){
cout<<"线性表a未能初始化!请重新输入!"<<endl;
}
else{
if(b_ok==0){
cout<<"线性表a未能初始化!请重新输入!"<<endl;
}
else{
int *pa=L1.elem;
int *pb=L2.elem;
L3.listsize=L3.length=L1.length+L2.length;
int *pc=L3.elem=(ElemType*)malloc(L3.listsize*sizeof(ElemType));
if(!L3.elem)
exit(OVERFLOW);
int *pa_last=L1.elem+L1.length-1;
int *pb_last=L2.elem+L2.length-1;
while(pa<=pa_last&&pb<=pb_last){
if(*pa<*pb)
*pc++=*pa++;
else *pc++=*pb++;
}
while(pa<=pa_last)
*pc++=*pa++;
while(pb<=pb_last)
*pc++=*pb++;
cout<<"线性表合并完毕:";
for(int j=0;j<L3.length;j++){ //合并后的查重操作
if(L3.elem[j] == L3.elem[j+1]){
for(int i=j+1;i<L3.length-1;i++){
L3.elem[i]=L3.elem[i+1];
}
L3.length--;
}
}
for(int i=0;i<L3.length;i++){
cout<<" "<<L3.elem[i];
}
}
}
cout<<endl;
}
//主函数
int main(){
int flag=1;
SqList La; //声明变量
SqList Lb; //某被调函数不需要修改原结构体,使用原结构体当中的数据
int infer;
while(flag){
cout<<"--------------------------------------"<<endl;
cout<<"*********1.初始化线性表***************"<<endl;
cout<<"*********2.销毁线性表*****************"<<endl;
cout<<"*********3.清空线性表*****************"<<endl;
cout<<"*********4.判断线性表是否为空*********"<<endl;//4-9只针对表a
cout<<"*********5.求线性表长度***************"<<endl;
cout<<"*********6.获取线性表中指定位置的元素*"<<endl;
cout<<"*********7.获取线性表元素的位置*******"<<endl;
cout<<"*********8.求前驱*********************"<<endl;
cout<<"*********9.求后驱*********************"<<endl;
cout<<"*********10.在线性表指定位置插入元素**"<<endl;
cout<<"*********11.删除线性表指定位置的元素**"<<endl;
cout<<"*********12.显示线性表****************"<<endl;
cout<<"*********13.合并两个非递减有序的线性表"<<endl;
cout<<"**********退出,输入一个负数**********"<<endl;
cout<<"--------------------------------------"<<endl;
cout<<"请输入对应的序号来进行相应的操作:";
cin>>infer;
switch(infer){
case 1:
InitList_Sq(La);
cout<<"成功建立a表"<<endl;
a_ok=1;
InitList_Sq(Lb);
cout<<"成功建立b表" <<endl;
b_ok=1;
break;
case 2:
cout<<"请输入a或b来表示想销毁的线性表:"<<endl;
char panding1;
if(panding1=='a'&&a_ok==1)
Destroylist_Sq(La);
if(panding1=='a'&&a_ok==0)
cout<<"请先初始化a表"<<endl;
if(panding1='b'&&b_ok==1)
Destroylist_Sq(Lb);
if(panding1=='b'&&b_ok==0)
cout<<"请先初始化b表"<<endl;
break;
case 3:
cout<<"请输入a或b来表示想清空的线性表:"<<endl;
char panding2;
if(panding2='a'&&a_ok==1)
ClearList_Sq(La);
if(panding2=='a'&&a_ok==0)
cout<<"请先初始化a表"<<endl;
if(panding2='b'&&b_ok==1)
ClearList_Sq(Lb);
if(panding2=='b'&&b_ok==0)
cout<<"请先初始化b表"<<endl;
break;
case 4:
if(a_ok==1)
EmptyList_Sq(La);
else cout<<"请先初始化a表"<<endl;
break;
case 5:
if(a_ok==1)
GetLength_Sq(La);
else cout<<"请先初始化a表"<<endl;
break;
case 6:
if(a_ok==1)
GetElem_Sq(La);
else cout<<"请先初始化a表"<<endl;
break;
case 7:
if(a_ok==1)
GetIndex_Sq(La);
else cout<<"请先初始化a表"<<endl;
break;
case 8:
if(a_ok==1)
PriorElem_Sq(La);
else cout<<"请先初始化a表"<<endl;
break;
case 9:
if(a_ok==1)
NextElem_Sq(La);
else cout<<"请先初始化a表"<<endl;
break;
case 10:
ListInsert(La,Lb);
cout<<endl;
break;
case 11:
ListDelete(La,Lb);
cout<<endl;
break;
case 12:
cout<<"请输入序号来表示想打印的线性表:"<<endl;
cout<<"1-线性表a"<<endl
<<"2-线性表b"<<endl;
int choose;
cin>>choose;
if(choose==1||choose==2){
if(choose==1&&a_ok==1)
ListPrint_Sq(La);
if(choose==1&&a_ok==0)
cout<<"请先初始化a表"<<endl;
if(choose==2&&b_ok==1)
ListPrint_Sq(Lb);
if(choose==2&&b_ok==0)
cout<<"请先初始化b表"<<endl;
}
else{
cout<<"输入错误,请重新输入您想要打印的线性表!"<<endl;
cin>>choose;
continue;
}
break;
case 13:
SqList Lc;
ListHebing(La,Lb,Lc);
cout<<endl;
break;
default:
if(infer<0){
flag=0;//while(flag)为假,结束循环
cout<<"成功退出程序,欢迎下次使用!"<<endl;
break;
}
else cout<<"输入有误!请重新尝试!"<<endl;
break;
}
}
return 0;
}