实验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。 (3)验收/测试用例 通过菜单调用各个操作,测试点:
|
#include <iostream>
using namespace std;
# define LIST_INIT_SIZE 100
# define LISTINCREMENT 10
#define OK 1 //执行成功
#define NO -1 //不存在
#define ERROR 0 //超出范围or执行失败
bool flag;
typedef int Status;
typedef int ElemType;
typedef struct {
ElemType* elem;
int length;
int listsize;
}SqList;
SqList L;
SqList lc;//合并表的结果
//初始化顺序表
Status InitList(SqList& l) {
l.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));//为数据元素开辟一维数组空间
if (!l.elem) {
cout << "线性表L储存分配失败,请重新操作" << endl;
return ERROR;
}
else {
l.length = 0;
l.listsize = LIST_INIT_SIZE;
cout << "线性表的存储空间分配成功!" << endl;
return OK;
}
}
//销毁
Status DestroyList(SqList& L)
{
free(L.elem);
L.elem = NULL;
L.length = 0;
L.listsize = 0;
flag = false;
return OK;
}
//清空
Status ListEmpty(SqList& L) {
L.length = 0;
return OK;
}
//判断数组是否为空
bool JudgeNull(SqList L) {
if (L.length == 0) {
return true;
}
else {
return false;
}
}
//求长度
int ListLength(SqList L) {
return L.length;
}
//获取线性表中指定位置的元素
Status GetElem(SqList L, int i, ElemType& e) {
if (i >= 0 && i < L.length)
{
e = L.elem[i - 1];
return OK;
}
else
{
return NO;
}
}
//获取线性表元素的位置
Status LocateElem(SqList L, ElemType e, int& z) {
for (int i = 0; i < L.length; i++)
{
if (L.elem[i] == e)
{
z = i + 1;
return OK;
}
}
return NO;
}
//前驱
Status PriorElem(SqList L, ElemType cur_e, ElemType& pre_e) {
for (int i = 0; i < L.length; i++)
{
if (L.elem[i] == cur_e)
{
if (i == 0) {
return ERROR;
}
else
{
pre_e = L.elem[i - 1];
return OK;
}
}
}
return NO;
}
//后继
Status NextElem(SqList L, ElemType cur_e, ElemType& next_e) {
for (int i = 0; i < L.length; i++)
{
if (L.elem[i] == cur_e)
{
if (i == L.length - 1) {
next_e = -1;
return ERROR;
}
else
{
next_e = L.elem[i + 1];
return OK;
}
}
}
return NO;
}
//插入
Status ListInsert(SqList& L, int i, ElemType e) {
if (i < 1 || i > L.length + 1) {
return ERROR;
}
if (L.length < L.listsize) {
int* q;
q = &L.elem[i - 1];
for (int* p = &(L.elem[L.length - 1]); p >= q; p--)
{
*(p + 1) = *p;
}
*q = e;
L.length += 1;
return OK;
}
}
//删除
Status DelElem(SqList& L, int i) {
if (i < 1 || i > L.length) {
return ERROR;
}
ElemType* q = &(L.elem[L.length - 1]);
//将删除位置后的所有元素向前移动
for (ElemType* p = &(L.elem[i - 1]); p < q; p++) {
*p = *(p + 1);
}
--L.length;
return OK;
}
//显示表
Status ShowTable(SqList l) {
cout << "表L:";
for (int i = 0; i < l.length; i++)
{
cout << l.elem[i] << " ";
}
cout << "" << endl;
return OK;
}
//合并表
Status ListMerge(SqList &lc) {
SqList la;
SqList lb;
//初始化表A
cout << endl;
la.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!la.elem)
{
cout << "线性表A存储分配失败,请您重新操作!" << endl;
}
else
{
la.length = 0;
la.listsize = LIST_INIT_SIZE;
cout << "线性表A的存储空间分配成功!" << endl;
cout << "请输入A中的元素,以负数结束:" << endl;
int a;
cin >> a;
while ( a > 0 )
{
la.length++;
la.elem[la.length - 1] = a;
cin >> a;
}
}
//初始化表B
cout << endl;
lb.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!lb.elem)
{
cout << "线性表B存储分配失败,请您重新操作!" << endl;
}
else
{
lb.length = 0;
lb.listsize = LIST_INIT_SIZE;
cout << "线性表B的存储空间分配成功!" << endl;
cout << "请输入B中的元素,以负数结束:" << endl;
int a;
cin >> a;
while (a > 0)
{
lb.length++;
lb.elem[lb.length - 1] = a;
cin >> a;
}
}
lc.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!lc.elem) {
cout << "合并线性表C创建失败,请重新创建!" << endl;
}
else {
cout << "合并线性表C的内存空间分配成功!" << endl;
cout << "合并线性表合并后:";
lc.listsize = lc.length = la.length + lb.length;
ElemType* pa = &la.elem[0];
ElemType* pb = &lb.elem[0];
ElemType* pc = &lc.elem[0];
ElemType* pa_end = &la.elem[la.length - 1];
ElemType* pb_end = &lb.elem[lb.length - 1];
while (pa <= pa_end && pb <= pb_end)//合并线性表A、B。
{
if (*pa <= *pb)
{
*pc = *pa;
pa++;
pc++;
}
else
{
*pc = *pb;
pb++;
pc++;
}
}
while (pa <= pa_end)//把表A中的剩余元素插入C。
{
*pc = *pa;
pa++;
pc++;
}
while (pb <= pb_end)//把表B中的剩余元素插入C。
{
*pc = *pb;
pb++;
pc++;
}
for (int i = 0; i <= lc.length - 1; i++)//查重,去重复值。
{
for (int j = i + 1; j <= lc.length - 1; j++) {
if (lc.elem[i] == lc.elem[j]) {
ElemType* q = &(lc.elem[lc.length - 1]);
for (ElemType* p = &(lc.elem[i]); p < q; p++) {
*p = *(p + 1);
}
--lc.length;
j--;
i--;//删除了重复的元素lc.elem[i]和lc.elem[j]向前移动一位
}
}
}
for (int i = 0; i <= lc.length - 1; i++)//输出
{
cout << lc.elem[i] << " ";
}
cout << endl;
}
return OK;
}
int main()
{
int n;
SqList la;
SqList lb;
ElemType tem;//定义一个临时元素
int address;//储存地址的值
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;
cout << "请输入选项:" << endl;
cin >> n;
while (n >= 0) {
switch (n)
{
case 1:
InitList(L);
flag = true;
break;
case 2:
if (flag) {
DestroyList(L);
cout << "表已销毁。" << endl;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 3:
if (flag) {
ListEmpty(L);
cout << "表已清空。" << endl;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 4:
if (flag) {
if (JudgeNull(L)) {
cout << "表L为空" << endl;
}
else
{
cout << "表L不为空" << endl;
}
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 5:
if (flag) {
cout << "表L的长度为" << ListLength(L) << endl;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 6:
if (flag) {
cout << "请输入元素在表中的位置:" << endl;
cin >> address;
if (GetElem(L, address, tem) == OK)
cout << "元素为:" << tem << endl;
else if (GetElem(L, address, tem) == NO)
cout << "不存在。" << endl;
break;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 7:
if (flag) {
cout << "请输入元素:" << endl;
cin >> tem;
if (LocateElem(L, tem, address) == OK)
cout << "元素在表中的位置为:" << address << endl;
else if (LocateElem(L, tem, address) == NO)
cout << "不存在。" << endl;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 8:
if (flag) {
ElemType res;
cout << "请输入元素:" << endl;
cin >> tem;
PriorElem(L, tem, res);
if (PriorElem(L, tem, res) == ERROR)
cout << "第一个元素没有前驱。" << endl;
else if (PriorElem(L, tem, res) == OK)
cout << "该元素的前驱为:" << res << endl;
else
cout << "不存在。" << endl;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 9:
if (flag) {
ElemType res;
cout << "请输入元素:" << endl;
cin >> tem;
NextElem(L, tem, res);
if (NextElem(L, tem, res) == ERROR) {
cout << "最后一个元素没有后继。" << endl;
}
else if (NextElem(L, tem, res) == OK) {
cout << "该元素的后继为:" << res << endl;
}
else {
cout << "不存在。" << endl;
}
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 10:
if (flag) {
cout << "请输入位置:" << endl;
cin >> address;
cout << "请输入元素:" << endl;
cin >> tem;
if (ListInsert(L, address, tem) == OK)
cout << "插入成功。" << endl;
else
cout << "位置超出范围。" << endl;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 11:
if (flag) {
cout << "请输入位置:" << endl;
cin >> address;
if (DelElem(L, address)== OK)
cout << "删除成功。" << endl;
else
cout << "位置超出范围。" << endl;
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 12:
if (flag) {
ShowTable(L);
}
else {
cout << "请先初始化表。" << endl;
}
break;
case 13:
ListMerge(lc);
break;
default:
break;
}
cout << "请输入选项:\n";
cin >> n;
}
}