# include<iostream>
# include<stdio.h>
# include<stdlib.h>
using namespace std;
#define LIST_INIT_SIZE 100 //线性表的初始容量
#define OK 1
#define OVERFLOW -2
#define ERROR 0
typedef int ElemType; //假设ElemType为int类型
typedef int Status; //状态类型,将Status定义为int
//定义顺序表结构体
typedef struct{
ElemType *elem; //指向存储数据元素的基地址
int length; //当前线性表的长度
int listsize; //当前分配的存储容量
}SqList;
//函数声明
Status InitList(SqList &L); //初始
Status DestroyList(SqList &L); //销毁
Status ClearList(SqList &L); //清空
Status ListEmpty(SqList L); //判断线性表是否为空
int ListLength(SqList L); //获取线性表长度
Status GetElem(SqList L,int i,ElemType &e); //获取指定位置元素
int LocateElem(SqList L,ElemType e); //获取元素位置
Status PriorElem(SqList L,ElemType cure_e,ElemType &pre_e); //获取前驱
Status NextElem(SqList L,ElemType crue_e,ElemType &next_e); //获取后驱
Status ListInsert(SqList &L,int i,ElemType e); //插入元素
Status ListDelete(SqList &L,int i,ElemType &e); //删除指定位置元素
Status DeleteElem(SqList &L,ElemType e); //根据元素值,删除元素
void SortList(SqList &L); //排序
void ShowList(SqList L); //显示
Status MergeList(SqList La,SqList Lb,SqList &Lc); //合并
//初始化线性表
Status InitList(SqList &L) { //构造一个空的线性表L
L.elem=(ElemType* )malloc(LIST_INIT_SIZE*sizeof(ElemType)); //为数据元素开辟一维数组空间
// LIST_INIT_SIZE一个宏定义,表示顺序表城市容量
//malloc 函数动态分配一片连续的内存空间
//sizeof(int)计算int类型的变量占几个字节
if(!L.elem) exit(OVERFLOW); //此时!L.elem为真,调用exit(OVERFLOW)终止运行
L.length=0; //空表长度为0
L.listsize=LIST_INIT_SIZE; //初始存储变量
return OK;
}
//销毁线性表
Status DestroyList(SqList &L){
free(L.elem); //释放内存
L.elem = NULL; //将已释放的指针设置为NULL,防止指针悬空
L.length = 0;
L.listsize = 0; //重置属性
return OK;
}
//清空线性表
Status ClearList(SqList &L){
L.length = 0;
return OK;
}
//判断线性表是否为空
Status ListEmpty(SqList L){
return L.length == 0 ? OK : ERROR; //空则返回OK,否则返回ERROR
}
//获取线性表长度
int ListLength(SqList L){
return L.length;
}
//获取指定位置元素
Status GetElem(SqList L,int i,ElemType &e){
if (i < 1 || i > L.length) return ERROR; //检查i是否有效
e = L.elem[i - 1]; //从0开始,所以i-1
return OK;
}
//获取元素位置
int LocateElem(SqList L,ElemType e){
for (int i = 0;i < L.length;++i){ //遍历
if(L.elem[i] == e)
return i + 1; //返回位序
}
return 0;
}
//获取前驱
Status PriorElem(SqList L,ElemType cur_e,ElemType &pre_e){
int pos = LocateElem(L,cur_e); //查找当前元素位置
if (pos <= 1 || pos == 0) return ERROR;
pre_e = L.elem[pos - 2]; //下标从0开始,而pose从1开始
return OK;
}
//获取后继
Status NextElem(SqList L,ElemType cur_e,ElemType &next_e){
int pos = LocateElem(L,cur_e);
if (pos == 0 || pos == L.length) return ERROR;
next_e = L.elem[pos - 1 + 1];
return OK;
}
//插入元素
Status ListInsert(SqList &L,int i,ElemType e){
if (i < 1 || i > L.length + 1) return ERROR; //输入位置是否有效
if (L.length >= L.listsize){
ElemType *newbase = (ElemType *)realloc(L.elem,(L.listsize + 10) * sizeof(ElemType));
//使用realloc函数重新分配内存
if (!newbase) exit(OVERFLOW); //扩容失败,调用exit终止函数
L.elem = newbase;
L.listsize += 10;
}
ElemType *p, *q;
q = &L.elem[i - 1];
for (p = &(L.elem[L.length - 1]);p>= q;--p){
*(p+1) = *p;
}
*q = e;
++L.length; //表长度加一
return OK;
}
//删除指定位置元素
Status ListDelete(SqList &L,int i,ElemType &e){
if (i < 1 || i > L.length) return ERROR;
e = L.elem[i - 1]; //将第i个位置的元素赋给e ,使得函数外部可获取到
for (int j = i;j < L.length;++j)
L.elem[j - 1] = L.elem[j]; //第i+1位置开始,元素依次向前移动一位
--L.length;
return OK;
}
//根据值删除元素
Status DeleteElem(SqList &L,ElemType e){
int pos = LocateElem(L,e); //将返回的位置存储在变量pos中
if (pos == 0) return ERROR; //未找到元素
ElemType temp; //用于存储删除的元素值
return ListDelete(L,pos,temp); //调用ListDelete删除位置为pos的元素
}
//排序(简单冒泡排序)
void SortList(SqList &L){
for (int i = 0;i < L.length - 1;++i) //外层循环,控制排序的轮数
for (int j = 0;j < L.length - i - 1;++j) //内层循环,控制每一轮中相邻元素比较交换
if (L.elem[j] > L.elem[j + 1]){
swap(L.elem[j],L.elem[j + 1]); //调用swap函数交换两个函数位置,较大的后移
}
}
//显示线性表
void ShowList(SqList L){
if (L.length == 0){ //判断顺序表是否为空
printf("线性表为空!\n");
return;
}
//非空表
printf("线性表内容: \n");
int i;
for (i = 0;i < L.length;i++){
printf("%d" ,L.elem[i]); //打印第i个元素
// 如果不是最后一个元素,则输出逗号
if (i < L.length - 1) {
printf(",");
}
}
printf("\n"); //所有元素打印
}
//合并两个非递减有序线性表
Status MergeList(SqList La,SqList Lb,SqList &Lc) {
int i = 0,j = 0,k = 0;
Lc.elem = (ElemType *)malloc((La.length + Lb.length) * sizeof(ElemType));
//为Lc分配内存空间,大小为La和Lb的长度之和乘以每个元素的大小
if (!Lc.elem) exit(OVERFLOW); //检查内存分配是否成功
while(i < La.length && j < Lb.length){
if (La.elem[i] <= Lb.elem[j]){
Lc.elem[k++] = La.elem[i++];
}else{
Lc.elem[k++] = Lb.elem[j++]; //将较小的元素放入Lc中
}
}
while(i < La.length) Lc.elem[k++] = La.elem[i++];
while(j < Lb.length) Lc.elem[k++] = Lb.elem[j++]; //遍历完后剩余元素插入Lc末尾
//对Lc去重
if (k == 0) {
Lc.length = 0;
Lc.listsize = 0;
return OK;
}
int writeIndex = 1; // 写入位置,第一个元素肯定保留
for (int readIndex = 1; readIndex < k; readIndex++) {
// 如果当前元素不同于前一个,则保留
if (Lc.elem[readIndex] != Lc.elem[writeIndex - 1]) {
Lc.elem[writeIndex] = Lc.elem[readIndex];
writeIndex++;
}
}
// 更新 Lc 的长度和存储空间
Lc.length = writeIndex;
Lc.listsize = writeIndex;
return OK;
}
//状态检查,用于main中判断当前线性表是否可用
#define IS_VALID(L)((L).elem != NULL)
#define IS_EMPTY(L)((L).length == 0)
int main()
{
SqList L;
L.elem = NULL; //初始状态设置为NULL,表示为初始化
int status;
int n = 1;//退出菜单的标记
cout<<"1------初始化一个线性表"<<endl;
cout<<"2------销毁线性表"<<endl;
cout<<"3------清空线性表"<<endl;
cout<<"4------判断线性表是否为空"<<endl;
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<<"14------显示线性表"<<endl;
cout<<"15------合并两个非递减有序的线性表"<<endl;
cout<<"退出,输入一个负数"<<endl;
while(n){//n不等于0 n!=0
int s; //选菜单
cout<<"请输入操作码,(退出时输入负数):\n";
scanf("%d",&s);
// 特殊处理:初始化操作(允许在任何状态下执行)
if (s == 1) {
if (IS_VALID(L)) {
printf("线性表已经初始化过了!如需重新开始,请先销毁。\n");
} else {
status = InitList(L);
if (status == OK) {
printf("线性表初始化成功!\n");
} else {
printf("初始化失败!内存分配失败。\n");
}
}
continue;
}
if (!IS_VALID(L)){
printf("线性表尚未初始化或已销毁,请先初始化!\n");
continue;
}
switch(s){
case 2:
cout<<"销毁线性表"<<endl;
status = DestroyList(L);
if (status == OK){
printf("线性表销毁成功!\n");
}else{
printf("线性表销毁失败!\n");
}
break;
case 3:
cout<<"清空线性表"<<endl;
status = ClearList(L);
if (status == OK){
printf("线性表清空成功!\n");
}else{
printf("线性表清空失败!\n");
}
break;
case 4:
cout<<"判断线性表是否为空"<<endl;
status = ListEmpty(L);
if (status == OK){
printf("线性表为空!\n");
}else{
printf("线性表不为空!\n");
}
break;
case 5:
cout<<"求线性表长度"<<endl;
printf("线性表当前长度为:%d\n",ListLength(L));
break;
case 6:
cout<<"获取线性表指定元素位置"<<endl;
int i;
ElemType e;
printf("请输入要获取的元素位置: ");
scanf("%d",&i); //读取输入的整数存入i中
status = GetElem(L,i,e); //调用GetElem函数,传入L,i,e
if (status == OK){
printf("第%d个元素为:%d\n", i, e);
}else{
printf("获取失败,位置无效\n");
}
break;
case 7:{ //形成局部作用域
cout<<"获取线性表中元素的位置"<<endl;
ElemType e;
printf("请输入要查找的元素值:");
scanf("%d", &e);
int pos = LocateElem(L,e);
if(pos != 0){
printf("该元素在第%d位\n", pos);
}else{
printf("该元素不存在\n");
}
break;
}
case 8:{
cout<<"求前驱"<<endl;
ElemType cur,pre;
printf("请输入当前元素值: ");
scanf("%d",&cur);
status = PriorElem(L,cur,pre);
if (status == OK){
printf("前驱元素为:%d\n",pre);
}else{
printf("没有前驱或元素不存在\n");
}
break;
}
case 9:{
cout<<"求后继"<<endl;
ElemType cur,next;
printf("请输入当前元素值: ");
scanf("%d",&cur);
status = NextElem(L,cur,next);
if (status == OK){
printf("后继元素为:%d\n",next);
}else{
printf("没有后继或元素不存在\n");
}
break;
}
case 10:{
cout<<"在线性表指定位置插入元素"<<endl;
int i;
ElemType e;
printf("请输入插入位置和值(中间用空格隔开): ");
scanf("%d %d",&i, &e);
status = ListInsert(L,i,e);
if(status == OK){
printf("插入成功!\n");
}else{
printf("插入失败,位置无效\n");
}
break;
}
case 11:{
cout<<"删除线性表指定位置元素"<<endl;
int i;
ElemType e;
printf("请输入要删除的元素位置:");
scanf("%d",&i);
status = ListDelete(L,i,e);
if (status == OK){
printf("已删除元素:%d\n",e);
}else{
printf("删除失败,位置无效!\n");
}
break;
}
case 12:{
cout<<"根据元素值,删除线性表中的元素"<<endl;
ElemType e;
printf("请输入要删除的元素值: ");
scanf("%d",&e);
status = DeleteElem(L,e);
if(status == OK) printf("删除成功!\n");
else printf("删除失败或元素不存在!\n");
break;
}
case 13:
cout<<"对线性表进行排序"<<endl;
SortList(L);
printf("线性表已排序!\n");
break;
case 14:
cout<<"显示线性表"<<endl;
ShowList(L);
break;
case 15:{
cout<<"合并两个非递减有序的线性表"<<endl;
SqList La,Lb,Lc;
InitList(La);
InitList(Lb);
int x;
printf("请输入La的数据(输入-1结束): ");
while(1){
scanf("%d",&x);
if (x == -1) break;
ListInsert(La,La.length + 1,x);
}
printf("请输入Lb的数据(输入-1结束): ");
while(1){
scanf("%d",&x);
if (x == -1) break;
ListInsert(Lb,Lb.length + 1,x);
}
SortList(La);
SortList(Lb); //排序确保非递减
MergeList(La,Lb,Lc);
printf("合并后的线性表为 ");
ShowList(Lc);
DestroyList(La);
DestroyList(Lb);
DestroyList(Lc);
//销毁,防止内存泄漏
break;
}
default:
if(s<0){
n = 0;
cout<<"程序退出成功,欢迎下次使用~~"<<endl;
break;
}
else
cout<<"您输入的指令有误,请重新输入~"<<endl;
}//switch
}//while
}//main 写出整体程序框架是怎么安排(菜单结构的设计)的,另外分别写出上述13个函数的设计思想和思路方法。