顺序表的实现(数据结构)

(1)实验目的

通过该实验,深入理解顺序表的逻辑结构、物理结构等概念,掌握顺序表基本操作的编程实现,注意顺序表插入、删除等操作过程中数据元素的移动现象,培养学生编写程序时,要考虑程序的健壮性,全面考虑问题,熟练掌握通过函数参数返回函数结果的办法。

(2)实验内容

编程实现顺序表下教材第二章定义的线性表的基本操作,并根据已经实现的基本操作(函数),通过调用函数,实现两个非递减有序的线性表的合并,注意,合并时,如果有重复的元素(一个表内部的重复元素和两个表之间的重复元素),请保留一个。

(3)实验要求

(a)求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值;(b)为了方便修改数据元素的类型,请使用类型重定义,可以方便修改线性表中的数据元素的类型;(c)大部分函数的返回结果应是函数执行是否成功的一种状态,执行成功了,才返回具体的结果值;(d)对每个功能进行测试时,要求把不合法的情况也测试一下。具体见下面的测试用例;(e)采用菜单形式对应各个操作,使其编成一个完整的小软件,参考界面如下。注意:程序运行过程中菜单不要做成刷屏的效果,测试过的数据不要清除,这样方便截图和查看。

注:

销毁是指free(L.elem);   L.elem=NULL;  L.length=0; L.listsize=0; return TRUE。

清空是指:L.length=0 ;return TRUE。

(4)验收/测试用例

通过菜单调用各个操作,测试点:

  1. 没有初始化前进行其他操作,程序是否能控制住;即,如果没有初始化线性表,其他的功能是无法正常进行的,如果选择进行其他操作,要提示先进行初始化;
  2. 先选择菜单1,初始化一个顺序表(初始化顺序表,是指初始化一个空的线性表,里面的元素个数是0);
  3. 选择菜单10,插入数据(位置, 数据),要测插入位置不合法的情况如:(0,1)、(2,1),正确插入3个数据(1,20)、(1,10)、(3,30);
  4. 显示顺序表中的数据,屏幕输出10, 20, 30;
  5. 判空,屏幕输出顺序表非空;
  6. 输出顺序表长度,屏幕输出3;
  7. 获取指定位置元素,要测指定位置在【1,3】范围之外的情况和之内的情况都要测试,非法的情况要做出合理的提示;
  8. 定位,输入:40, 输出:不存在,输入20,输出位置为2;
  9. 求直接前驱,要测求第一个元素的前驱、不存在顺序表中的元素的直接前驱,其他元素的直接前驱;输入10,输出:第一个元素没有前驱,输入20,输出前驱是10,输入40,输出该元素不存在;
  10. 求直接后继,要测最后一个元素的后继、不存在顺序表中的元素的直接后继,其他元素的直接后继;同上求前驱;
  11. 删除,要测位置在【1,3】范围之外的情况和之内的情况,非法的情况要做出合理的提示;
  12. 清空操作后再测长度,判断是否为空;清空后,测试菜单6到11的功能,看是否能够正确提示。
  13. 销毁顺序表,销毁线性表之后还能不能做插入,删除等操作,如果选其他操作,就要提示线性表已经销毁不存在;
  14. 测试合并操作,第一个线性表中的元素是(2,3,3,4,5),第二个线性表中的内容是(1,4,5,6,6,7),合并后的结果,请输出
#include<iostream>
#include <cstdlib> 
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
using namespace std;
typedef struct{
	int *elem;
	int length;
	int listsize;
}SqList;
bool initList(SqList &L){
		L.elem=(int * )malloc(LIST_INIT_SIZE*sizeof(int));
		if(! L.elem)cout<<"分配失败"<<endl;
		L.length=0;
		L.listsize=LIST_INIT_SIZE;
		cout<<"分配成功"<<endl;
		return true;
}
/*这段代码是C++中用于初始化一个顺序列表(SqList)的函数。函数名为initList,输入参数是一个SqList类型的引用,也被 命名为L
在函数内部,首先通过调用malloc函数为L.elem分配内存,该内存的大小为LIST_INIT_SIZE(预定义的整数常量)乘以int类型的大小。将分配的内存地址赋给L.elem,如果内存分配失败(malloc返回NULL),则会输出 '分配失败'。  
  
然后,将L.length(列表的当前长度)设置为0,表示列表为空。  
  
接着,将L.listsize(列表的最大容量)设置为LIST_INIT_SIZE,表示列表的初始容量。  
  
最后,输出 '分配成功',并返回true,表示函数执行成功。  
  
这个函数的主要目的是初始化顺序列表,包括分配内存、设置列表长度和容量,并在必要时输出错误信息。*/
void destroy(SqList &L){
	free(L.elem);
	L.elem=NULL;
	L.length=0;
	L.listsize=0;
	cout<<"销毁成功"<<endl;
}
//销毁链表
void clear(SqList &L){
	if(!L.elem)cout<<"该链表已销毁"<<endl;
	else{L.length=0;
	cout<<"清空成功"<<endl; 
	} 
} 
//清空链表
bool jud(SqList &L){
	if(!L.elem)cout<<"该表已销毁"<<endl;
	else{
		if(L.length==0) {
				cout<<"线性表为空"<<endl;
				return true ;
			}else {cout<<"线性表不为空"<<endl;
				return false;
				
			}
	}
}
int Listlength(SqList &L){
	if(!L.elem)cout<<"该表已销毁"<<endl;
	else return L.length;
}
int  Getelem(SqList L,int i,int &e){
	if(!L.elem)cout<<"该表已销毁"<<endl;
	else{if(L.length>0){
		if(i>0&&i<=L.length){
			e=L.elem[i-1];
			cout<<e<<endl;
		}
		else cout<<"输入错误"<<endl; 
	}
	else cout<<"该线性表不存在,无法获取元素"<<endl;}
}
void Getload(SqList &L,int e){
	if(!L.elem)cout<<"该表已销毁"<<endl;
	else{cout<<"请输入想查找的元素"<<endl;
	cin>>e;
	int i;
	for(i=0;i<L.length;i++){
		if(L.elem[i]==e){
			cout<<"位置为"<<i+1<<endl;
			}
	}
	if(i=L.length&&L.elem[i-1]!=e){
		cout<<"输入错误"<<endl;
	}
	}
}
int front(SqList *L,int i,int &e){
	if(!L->elem)cout<<"该表已销毁"<<endl;
	else{if(i>1&&i<=L->length){
		cout<<"前驱为"<<endl;
		e=L->elem[i-2];
		cout<<e<<endl;
	}else cout<<"输入错误"<<endl;}
}
int behind(SqList *L,int i,int &e){
	if(!L->elem)cout<<"该表已销毁"<<endl;
	else{if(i>0&&i<L->length){
			cout<<"后继为"<<endl;
			e=L->elem[i];
			cout<<e<<endl;
		}else cout<<"输入错误"<<endl;}
}
//前驱后缀
 void insert(SqList *L,int i,int e){
	if((i>0)&&(i<=L->listsize)){
		if(L->length==L->listsize){
			int *newbase=(int * )realloc(L->elem, (LIST_INIT_SIZE+LISTINCREMENT)*sizeof(int));
			if(!newbase)cout<<"存储分配失败"<<endl;
			int m;
			for(m=0;m<i-1;m++){
				newbase[m]=L->elem[m];
			}
			newbase[i-1]=e;
			for(m=i;m<L->length+1;m++){
				newbase[m]=L->elem[m-1];
			}
			L->elem=newbase;
			L->listsize=LIST_INIT_SIZE+LISTINCREMENT;
			L->length=L->length+1;
			cout<<"插入成功"<<"\n";
		}else {
			int m;
			
			for(m=L->listsize-1;m>=i;m--){
				L->elem[m]=L->elem[m-1];
			}
			
			L->elem[i-1]=e;
L->length=L->length+1;
			cout<<"插入成功"<<"\n";
		}	
	}else cout<<"输入错误"<<"\n";
}
void delate(SqList &L,int i,int &e){
	if(i>0&&i<=L.length){
		int m;
		if(i==L.length)
        {
	    L.length=L.length-1;
	    cout<<"删除成功"<<endl;
}else {
	for(m=i-1;m<L.length-1;m++){
				L.elem[m]=L.elem[m+1];
			}
			cout<<"删除成功"<<endl;
			L.length=L.length-1;
}
	}else cout<<"输入错误"<<endl;
}
void display(SqList &L){
	int m;
	for(m=0;m<L.length;m++){
		cout<<L.elem[m]<<" ";
	}
}
bool merge(SqList L1,SqList L2,SqList &L){
	int i=0;
	int j=0;
	int k=0;
	while(i<L1.length&&j<L2.length){
		if(L1.elem[i]>L2.elem[j]){
			L.elem[k]=L1.elem[i];
			++i;
		}else{
			L.elem[k]=L2.elem[j];
			++j;
		}
		++k;
	}
	//这段 代码是用于合并两个有序列表L1和L2的函数,结果存储在列表L中。代码首先定义了三个指针(i, j, k),并设置它们都为0。然后,它进入一个循环,在这个循环中,它会比较L1和L2的当前元素(i和j索引的元素)。如果L1的当前元素大于L2的当前元素,它会将L1的当前元素添加到L中,然后增加i的值。否则,它会将L2的当前元素添加到L中,并增加j的值。一旦循环结束,任何剩余的元素(在L1或L2中)将被添加到结果列表L中。注意,这个函数假设列表L有足够的空间来存储合并后的元素。
	if(i==L1.length){
		for(int m=j;m<L2.length;m++,k++){
			L.elem[k]=L2.elem[m];
		}
	}else if(j==L2.length){
		for(int m=i;m<L1.length;m++,k++){
					L.elem[k]=L1.elem[m];
				}
	}
	cout<<"线性表为:";
	for(int i=0;i<k;i++){
		cout<<L.elem[i]<<" ";
	}
	
}
int main(){
	SqList L;
	SqList L1;
	SqList L2;
	initList(L);
	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<<"退出,输入一个负数!";
	while(true){
		int choice;
		int e;
		int i;
		cin>>choice;
	switch(choice) {
		case 1:
		initList(L);
		break;
		case 2:
			destroy(L);
			break;
		case 3:
			clear(L);
			break;
		case 4:
			jud(L);
			break;
		case 5:
			cout<<"长度是"<<Listlength(L);
			break;
		case 6:
			cout<<"输入查找的位置"<<endl;
			cin>>i;
			Getelem(L,i,e);
			break;
		case 7:
			int e;
			Getload(L,e);
			break;
		case 8:
			cout<<"输入第几个位置"<<endl;
			cin>>i;
			front(&L,i,e);
			break;
		case 9:
			cout<<"输入第几个位置"<<endl;
			cin>>i;
			behind(&L,i,e);
			break;
		case 10:
			cout<<"输入位置"<<endl;
			cout<<"输入数字"<<endl;
			cin>>i;
			cin>>e;
			insert(&L,i,e);
			break;
		case 11:
			cout<<"输入删除元素的位置"<<endl;
			cin>>i;
			delate(L,i,e);
			break;
		case 12:
			display(L);
			break;
		case 13:
			int n;
			cout<<"输入L1的元素个数"<<endl;
			cin>>n;
			initList(L1);
			for(int k=0;k<n;k++){
				cout<<"输入位置"<<endl;
				cout<<"输入数值"<<endl;
				cin>>i;
				cin>>e;
				insert(&L1,i,e);
			}
			cout<<"输入L2的元素个数"<<endl;
				cin>>n;
				initList(L2);
				for(int k=0;k<n;k++){
				cout<<"输入位置"<<endl;
					cout<<"输入数值"<<endl;
							cin>>i;
							cin>>e;
							insert(&L2,i,e);
						}
			merge(L1,L2,L);
			break;
		default:
			if(choice<0){
				cout<<"程序已结束";
				break;
			}
	}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

invincible_Tang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值