数据结构实验2---顺序表的实现

(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>
using namespace std;
typedef int Status;
typedef int ElemType;
#define LIST_INIT_SIZE 100 //符号常量 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
#define OK 1
#define ERROR 0
#define true 1
#define false 0

typedef struct {
	ElemType* elem;//表基址,申请的内存首地址
	int length;//表长(特指元素个数)
	int listsize;//表当前存储容量(最大长度)
}Sqlist;

//1.初始化
//构造一个空的线性表L
Status InitList(Sqlist& L) {
	//为数据元素开辟一维数组空间
	L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
	if (!L.elem) {
		printf("存储空间分配失败\n");
		exit(OVERFLOW);
	}//存储分配失败
	L.length = 0;//空表长度为零
	L.listsize = LIST_INIT_SIZE;//初始存储容量
	printf("线性表初始化成功\n");
	return OK;
}

//2.销毁
Status DestroyList(Sqlist& L) {
	free(L.elem);
	L.elem = NULL;//重置elem的值为null
	L.length = 0;//重置线性表元素个数为0
	L.listsize = 0;//重置线性表存储容量为0
	printf("线性表销毁成功\n");
	return OK;
}


//3.清空
Status ClearList(Sqlist& L) {
	L.length = 0;//重置线性表容量为0
	printf("线性表已清空\n");
	return OK;
}

//4.判断是否为空
Status ListEmpty(Sqlist& L) {
	if (L.length != 0) {
		printf("线性表不为空\n");
		return false;
	}
	else//如果线性表元素为0,则说明线性表为空
		printf("线性表为空\n");
	return true;
}


//5.求线性表长度
Status ListLength(Sqlist& L) {
	int x = L.length;
	printf("线性表长度为%d\n", x);
	return OK;
}

//6.获取指定位置的元素
Status GetElem(Sqlist& L, int i, ElemType e) {
	if (L.length == 0) {
		printf("线性表为空\n");
		return ERROR;
	}
	if (i - 1 < 0 || i > L.length) {//判断元素的位置是否出界
		printf("请输入有效数字\n");
		return ERROR;
	}
	else {
		e = L.elem[i - 1];
		printf("第%d个位置的元素是%d\n", i, e);
		return OK;
	}
}

//7.获取元素的位置
Status LocateElem(Sqlist& L, ElemType e) {
	if (L.length == 0) {
		printf("线性表为空\n");
		return ERROR;
	}
	int i = 1;
	for (i = 1;i <= L.length;i++) {
		if (e == L.elem[i - 1]) {
			int l = i;
			printf("元素%d的位置是%d\n", e, l);
			return OK;
		}
		if (i == L.length && e != L.elem[L.length - 1]) {
			printf("不存在该元素\n");
			return ERROR;
		}
	}
}

//8.前驱
Status PriorElem(Sqlist& L, ElemType e, ElemType prior_e) {
	int i = 1;
	if (L.length == 0) {
		printf("线性表为空\n");
		return false;
	}
	if (e != L.elem[0]) {
		while (i <= L.length && e != L.elem[i - 1]) {//当输入的值与元素范围相同时,跳出循环
			i++;
		}
		if (i <= L.length || e == L.elem[i - 1]) {
			prior_e = L.elem[i - 2];
			printf("元素%d的前驱为%d\n", e, prior_e);
		}
		else {
			cout << "该元素不存在" << endl;
		}
	}
	else {
		cout << "首元素无前驱" << endl;
	}
}

//9.后继
Status NextElem(Sqlist& L, ElemType e, ElemType next_e) {
	int i = 1;
	if (L.length == 0) {
		printf("线性表为空\n");
		return false;
	}
	for (int i = 1;i <= L.length;i++) {
		if (i < L.length && e == L.elem[i - 1]) {
			next_e = L.elem[i];
			printf("元素%d的后继为%d\n", e, next_e);
			return OK;
		}
		else if (i == L.length && e != L.elem[i - 1]) {
			cout << "该元素不存在" << endl;
			return ERROR;
		}
		else if (i == L.length && e == L.elem[i - 1]) {
			printf("尾元素无后继\n");
			return ERROR;
		}
	}
}


//10.在指定位置插入元素
Status ListInsert(Sqlist& L, int i, ElemType e) {
	ElemType* newbase;
	int* q, * p;
	if (i<1 || i>L.length + 1) {//i的合法位置为0<i<L.length+1
		cout << "插入位置不合法" << endl;//判断插入位置是否合法
		return ERROR;
	}
	if (L.length >= L.listsize) {//表示如果存储空间已满,增加内存
		newbase = (ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
		if (!newbase) {//存储空间分配失败,异常退出
			printf("存储空间分配失败\n");
			exit(OVERFLOW);
		}
		L.elem = newbase;//新的存储空间基址
		L.listsize += LISTINCREMENT;
	}
	q = &L.elem[i - 1];
	p = &L.elem[L.length - 1];//L.elem[L.length - 1]为数组中的最后一个元素
	for (p;p >= q;--p)
		*(p + 1) = *p;//插入位置及以后位置向后移
	*q = e;//将元素插入
	++L.length;//插入后长度加1
	cout << "插入成功" << endl;
	return OK;
}

//11.删除指定位置的元素
Status DeleteList(Sqlist& L, int i) {
	int* p, * q;
	if (L.length == 0) {
		cout << "线性表为空" << endl;
		return ERROR;
	}
	//i的合法地址:0<i<L.length
	if (i<1 || i>L.length) {//判断删除地址是否合法
		printf("请输入一个有效的位置:\n");
		return ERROR;
	}
	p = &L.elem[i - 1];//p为被删除元素的位置
	ElemType e = *p;
	q = &L.elem[L.length - 1];//q为表尾元素
	for (p;p <= q;p++)
		*p = *(p + 1);//将被删除元素之后的元素前移
	cout << "删除成功" << endl;
	--L.length;//表长减一
	return OK;
}

//12.显示线性表
Status PrintList(Sqlist& L) {
	if (L.length == 0) {
		cout << "线性表为空" << endl;
	}
	for (int i = 0;i < L.length;i++) {
		int x = L.elem[i];
		cout << x << " ";
	}
	cout << "" << endl;
	return OK;
}

// 为线性表赋值
void InputElem(Sqlist& LA, int i, Sqlist& LB, int j)//创建线性表LA,LB.
{
	InitList(LA);              //初始化LA
	cout << "请为顺序表A赋值,输入负数退出!" << endl;
	for (i = 0; i < LA.listsize; i++)
	{
		cin >> LA.elem[i];
		if (LA.elem[i] < 0)       //退出输入状态
		{
			break;
		}
		LA.length = i + 1;
	}//for
	//LA.listsize = sizeof(LA.elem);

	InitList(LB);              //初始化LB
	cout << "请为顺序表B赋值,输入负数退出!" << endl;
	for (j = 0; j < LB.listsize; j++)
	{
		cin >> LB.elem[j];
		if (LB.elem[j] < 0)
		{
			break;
		}

		LB.length = j + 1;
	}//for
	//LB.listsize = sizeof(LB.elem);
}

//13--合并两个非递减有序的线性表
Status UnionList(Sqlist LA, Sqlist LB, Sqlist& LC)
{

	int i = 1;
	int j = 1;
	int k = 1;
	//赋值
	InputElem(LA, i, LB, j);
	int La_len = ListLength(LA);
	int Lb_len = ListLength(LB);
	while ((i <= La_len) && (j <= Lb_len))
	{
		if (LA.elem[i - 1] <= LB.elem[j - 1]) {
			ListInsert(LC, k, LA.elem[i - 1]);
			i++;
			k++;
		}
		else {
			ListInsert(LC, k, LB.elem[j - 1]);
			j++;
			k++;
		}
	}//while
	//将较长的线性表剩余的元素插入
	while (i <= LA.length)
	{
		ListInsert(LC, k, LA.elem[i - 1]);
		i++;
		k++;
	}
	while (j <= LB.length)
	{
		ListInsert(LC, k, LB.elem[j - 1]);
		j++;
		k++;
	}
	//去重
	for (int a = 0; a < LC.length; a++)
	{
		for (int b = a + 1; b < LC.length; b++)
		{
			if (LC.elem[a] == LC.elem[b])
			{
				DeleteList(LC, b);
				b--;
			}
		}
	}
	PrintList(LC);
	return OK;
}

int main() {
	Sqlist La, Lb, Lc;
	bool initlist = false;
	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 << "退出,输入一个负数!" << endl;
	int n = 1;
	while (n) {
		int i;
		cout << "请输入你选择的功能:";
		scanf_s("%d", &i);
		switch (i) {
		case 1:
			InitList(La);
			initlist = true;
			break;
		case 2:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			DestroyList(La);
			initlist = false;
			break;
		case 3:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			ClearList(La);
			break;
		case 4:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			ListEmpty(La);
			break;
		case 5:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			ListLength(La);
			break;
		case 6:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			else {
				ElemType e = 0;
				int i = 0;
				cout << "请输入要获取位置的元素:";
				cin >> i;
				GetElem(La, i, e);
			}
			break;
		case 7:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			{
				ElemType e = 0;
				cout << "请输入要获取位置的元素:";
				cin >> e;
				LocateElem(La, e);
			}
			break;
		case 8:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			{
				ElemType e = 0;
				ElemType prior_e = 0;
				printf("请输入元素:");
				cin >> e;
				PriorElem(La, e, prior_e);
			}
			break;
		case 9:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			{
				ElemType e = 0;
				ElemType next_e = 0;
				cout << "请输入元素:";
				cin >> e;
				NextElem(La, e, next_e);
			}
			break;
		case 10:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			{
				int i = 0;
				ElemType e = 0;
				cout << "插入位置是:";
				cin >> i;
				cout << "插入元素为:";
				cin >> e;
				ListInsert(La, i, e);
			}
			break;
		case 11:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			{int i = 0;
			cout << "请输入删除的位置:";
			cin >> i;
			DeleteList(La, i);
			}
			break;
		case 12:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			PrintList(La);
			break;
		case 13:
			if (initlist != true) {
				printf("请先进行初始化:\n");
				break;
			}
			InitList(La);
			InitList(Lb);
			InitList(Lc);
			UnionList(La, Lb, Lc);
			break;
		default:
			if (i < 0) {
				cout << "退出程序" << endl;
				n = 0;
			}
		}
	}
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

用户1234567890

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

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

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

打赏作者

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

抵扣说明:

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

余额充值