线性表的基本操作及其应用
一、实验目的
1、帮助读者复习C++语言程序设计中的知识。
2、熟悉线性表的逻辑结构。
3、熟悉线性表的基本运算在两种存储结构上的实现,其中以熟悉链表的操作为侧重点。
二、实验内容
本次实验提供4个题目,每个题目都标有难度系数,*越多难度越大,学生可以根据自己的情况选做!
题目一:单链表的基本操作(*)
[问题描述]
实现带头结点的单链表的建立、求长度,取元素、修改元素、插入、删除等单链表的基本操作。
[基本要求]
(1)依次从键盘读入数据,建立带头结点的单链表;
(2)输出单链表中的数据元素
(3)求单链表的长度;
(4)根据指定条件能够取元素和修改元素;
(5)实现在指定位置插入和删除元素的功能。
[测试数据]
由学生任意指定。
1、总体设计
节点 |
依次从键盘读入数据,建立带头结点的单链表 |
输出单链表中的元素 |
求单链表的长度
|
指定位置 取 / 修改元素 |
指定位置删除/ 插入元素 |
单链表 |
2、详细设计及重要代码:
voidCreateList_L(LinkList &L)
{//依次从键盘读入数据,建立带头结点的单链表
int i,n;
LNode *p;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
cout<<"请输入元素个数:"<<endl;
cin>>n;
cout<<"请输入待插入链表的数据:(例如: 34,67,3,-9,45,...)"<<endl;
for(i=n;i>0;--i)
{
p=(LinkList)malloc(sizeof(LNode));
cin>>p->data;
p->next=L->next;
L->next=p;
}
}
voidInsretdataList_L(LinkList &L)
{//指定位置插入元素
LNode *p;
int j=0;
p=L;
int i;
cout<<"请输入指定位置:"<<endl;
cin>>i;
while(p&&j<i-1)
{
p=p->next;++j;
}
if(!p||j>i-1)
{
cout<<"第"<<i<<"数据不存在!"<<endl;
return;
}
int e;
cout<<"请输入待插入的元素:"<<endl;
cin>>e;
LNode *s;
s=new LNode[sizeof(LNode)]; //创建一个新节点
s->data=e;
s->next=p->next;
p->next=s;
}
voidDeletedataList_L(LinkList &L)
{//指定位置删除元素
LNode *p,*q;
int j=0;
p=L;
int i;
cout<<"请输入指定位置:"<<endl;
cin>>i;
while(p&&j<i-1)
{
p=p->next;++j;
}
if(!p||j>i-1)
{
cout<<"第"<<i<<"数据不存在!"<<endl;
return;
}
q=p->next;
p->next=q->next;
free(q);
}
3、功能截图展示:
输出:
插入元素:
4、程序清单
#include<stdio.h>
#include<iostream>
usingnamespace std;
typedefstruct LNode
{ int data;
struct LNode *next;
}LNode,*LinkList;
voidCreateList_L(LinkList &L)
{//依次从键盘读入数据,建立带头结点的单链表
int i,n;
LNode *p;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
cout<<"请输入元素个数:"<<endl;
cin>>n;
cout<<"请输入待插入链表的数据:(例如: 34,67,3,-9,45,...)"<<endl;
for(i=n;i>0;--i)
{
p=(LinkList)malloc(sizeof(LNode));
cin>>p->data;
p->next=L->next;
L->next=p;
}
}
voidPrintfList_L(LinkList &L)
{//输出单链表中的元素
LNode *p;
p=L->next;
while(p)
{
cout<<p->data<<"";
p=p->next;
}
cout<<endl;
}
voidGetlendthList_L(LinkList &L)
{//求单链表的长度
int i=0;
LNode *p;
p=L->next;
while(p)
{
++i;
p=p->next;
}
cout<<"该单链表元素个数位:"<<i<<endl;
}
voidGetdataList_L(LinkList &L)
{//指定位置取元素
LNode *p;
int j=1;
p=L->next;int i;
cout<<"请输入指定位置:"<<endl;
cin>>i;
while(p&&j<i)
{
p=p->next;++j;
}
if(!p||j>i)
{
cout<<"第"<<i<<"数据不存在!"<<endl;
return;
}
cout<<"第"<<i<<"个位置的元素是:"<<p->data<<endl;
}
voidModifydataList_L(LinkList &L)
{//指定位置修改元素
LNode *p;
int j=1;
p=L->next;
int i;
cout<<"请输入指定位置:"<<endl;
cin>>i;
while(p&&j<i)
{
p=p->next;++j;
}
if(!p||j>i)
{
cout<<"第"<<i<<"数据不存在!"<<endl;
return;
}
cout<<"请输入修改后的元素:"<<endl;
cin>>p->data;
}
voidInsretdataList_L(LinkList &L)
{//指定位置插入元素
LNode *p;
int j=0;
p=L;
int i;
cout<<"请输入指定位置:"<<endl;
cin>>i;
while(p&&j<i-1)
{
p=p->next;++j;
}
if(!p||j>i-1)
{
cout<<"第"<<i<<"数据不存在!"<<endl;
return;
}
int e;
cout<<"请输入待插入的元素:"<<endl;
cin>>e;
LNode *s;
s=new LNode[sizeof(LNode)]; //创建一个新节点
s->data=e;
s->next=p->next;
p->next=s;
}
voidDeletedataList_L(LinkList &L)
{//指定位置删除元素
LNode *p,*q;
int j=0;
p=L;
int i;
cout<<"请输入指定位置:"<<endl;
cin>>i;
while(p&&j<i-1)
{
p=p->next;++j;
}
if(!p||j>i-1)
{
cout<<"第"<<i<<"数据不存在!"<<endl;
return;
}
q=p->next;
p->next=q->next;
free(q);
}
intmain()
{
LinkList L;
LNode *p;
int e;
char a;
int i,j,n=1;
int LListNodeNum;
while(n!=8)
{
system("cls");
cout<<"======================================="<<endl;
cout<<"=========单链表的基本操作=============="<<endl;
cout<<"======================================="<<endl;
cout<<"--------1、创建单链表------------------"<<endl;
cout<<"--------2、输出单链表所有元素----------"<<endl;
cout<<"--------3、获取单链表长度--------------"<<endl;
cout<<"--------4、指定位置取元素--------------"<<endl;
cout<<"--------5、指定位置修改元素------------"<<endl;
cout<<"--------6、指定位置插入元素------------"<<endl;
cout<<"--------7、指定位置删除元素------------"<<endl;
cout<<"======================================="<<endl;
skip: cout<<"请选择功能:"<<endl;
cin>>n;
switch(n)
{
case 1:CreateList_L(L);break;
case 2:PrintfList_L(L);break;
case 3:GetlendthList_L(L);break;
case 4:GetdataList_L(L);break;
case 5:ModifydataList_L(L);break;
case 6:InsretdataList_L(L);break;
case 7:DeletedataList_L(L);break;
degault:goto skip;
}
skip1: cout<<"是否退出:(Y/N或y/n)"<<endl;
cin>>a;
if(a=='y'||a=='Y')
break;
else if(a=='n'||a=='N')continue;
else
{cout<<"输入有误,请重新输入!"<<endl;
goto skip1;
}
return 0;
}
}
题目二:约瑟夫环(**)
[问题描述]
约瑟夫(Joseph)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。
[基本要求]
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
[测试数据]
由学生任意指定。
如:m的初值为20;n的值为7;密码:3,1,7,2,4,8,4;
(正确的输出结果应为6,1,4,7,2,3,5)。
(报告上要求写出多批数据测试结果)
[实现提示]
程序运行后首先要求用户输入初始报数上限值m,人数n,(设n≤30)。然后输入各人的密码。
[选作内容]
向上述程序中添加在顺序结构上实现的部分。
1、总体设计(设计思想)
构造一个单向循环链表,每一个节点即代表一个人,因为最后要求的是输出出列的顺序印出各人的编号,所以在创建链表的时候给节点结构体多加一个参数(属性)来记录每个人的编号。
2、详细设计及重要代码:
本题的重点就就构建单向循环链表,只要把这个弄好了,我的思路是先创建一个节点,让它的next指针指向自己,然后向它后面插入节点,插入的节点的next指针一直指向字一个节点,这样就构成了地啊想循环链表
3、功能截图展示:
4、程序清单
#include<iostream>
usingnamespace std;
typedefstruct LNode
{
int num;
int code;
struct LNode *next;
}LNode,*Link;
voidInitList(Link &L) //初始化循环链表
{
L = new LNode;
L->next = L;
}
voidLeave(Link &L, int n, int m)
{
if (!L)
{
cout << "队列链表不存在!!!" << endl;
return;
}
Link p = L, e, q;
cout << "请输入人们持有的密码:";
cin >> p->code;
p->num = 1; //无头节点所以要先赋值
for (int i = 1; i < n; i++) //人们入队
{
e = new LNode;
e->num = i + 1;
cin >> e->code;
e->next = L;
p->next = e;
p = p->next;
}
q = p;
p = p->next;
cout << "出队的人顺序为:";
while (1)
{
if (p->next == p) //只剩下一人
{
cout << p->num<< endl;
delete p;
break;
}
m--;
if (m == 0) //第m个
{
cout << p->num<< ' ';
q->next =p->next; //删除节点
m = p->code; //给m重新赋值
e = p;
p = p->next;
delete e;
}
else
{
q = p;
p = p->next;
}
}
}
intmain()
{
int n, m;
while (1)
{
Link L;
InitList(L);
cout << "请输入要输入的数据的个数(0结束):";
cin >> n;
if (n == 0&&n>30)
break;
cout << "请输入上限值为:";
cin >> m;
Leave(L, n, m);
}
return 0;
}
题目三:Dr.Kong设计了一件艺术品(****)
[问题描述]
Dr.Kong设计了一件艺术品,该艺术品由N个构件堆叠而成,N个构件从高到低按层编号依次为1,2,……,N。艺术品展出后,引起了强烈的反映。Dr.Kong观察到,人们尤其对作品的高端部分评价甚多。
狂热的Dr.Kong一激动,对组成该艺术品的N个构件重新组合,比如:把第6层到第12层的构件搬下来,想一想,然后整体放到剩下构件的第7层下面;过一会儿,又把第2层到第9层的构件搬下来,整体放到剩下构件的第1层下面等等。于是,Dr.Kong在进行了连续若干次“搬来搬去”后,还是这N个构件,又诞生了一件新的艺术品。
编程:请输出新的艺术品最高十层构件的编号。
【标准输入】
第一行: N K 表示构件的总数和“搬来搬去”的总次数
第2~K+1行:A B C 表示要搬动的构件(即从第A层到第B层)整个放在第C层下面;
如果C等于0,则要搬动的构件将放到最高层。
【标准输出】
由十行组成,分别为组成新艺术品的第一层到第十层构件的编号。
【约束条件】
(1) 10≤N≤20000 1≤k≤1000
(2) 1≤A≤B≤N, 0≤C≤N-(B-A+1)
【 样 例 】
提示:样例中仅是常规的测试数据输入及对应结果,特殊情况需要全面考虑,自己设计测试数据验证算法的健壮性。
标准输入(测试数据):
13 3
6 12 1
2 9 0
10 13 8
标准输出结果:
6 7 8 9 10 11 12 2 3 4 5 13 1
1、总体设计(设计思想)
本题的重点是构建单链表,截取单链表。首先,构建从1~n的单链表,截取单链表跟删除单链表的节点相似,吧指针指向控制好就行了。
3、功能截图展示:
3、程序清单
#include<stdio.h>
#include<iostream>
usingnamespace std;
typedefstruct LNode
{ int data;
struct LNode *next;
}LNode,*LinkList;
voidCreateList_L(LinkList &L,int n)
{//创建节点数为n的单链表
LNode *p;
L= new LNode[sizeof(LNode)]; //头结点
L->next=NULL;
for(int i=n;i>0;i--)
{
p=new LNode[sizeof(LNode)];
p->data=i;
p->next=L->next;
L->next=p;
}
}
voidMoveList_L(LinkList &L,int l,int r,int n)
{//移动结点的函数
int i=0;
LNode *p=L,*q=L;
LNode *newL;
while(p&&i<l-1)
{
p=p->next;
++i;
}
i=0;
while(q&&i<r)
{
q=q->next;
++i;
}
newL=p->next; //将截取下来的一段单链表保存在newL中
p->next=q->next;
i=0;p=L;
while(p&&i<n)
{
p=p->next;
i++;
}
q->next=p->next; //插入之前截取下来的单链表newL
p->next=newL;
}
voidPrintfList_L(LinkList &L)
{//输出单链表中的元素
LNode *p;
p=L->next;
while(p)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
intmain()
{
LNode *L;
int n,k,a,b,c;
cout<<"请输入构件的总数和“搬来搬去”的总次数:"<<endl;
cin>>n>>k;
CreateList_L(L,n);
cout<<"请输入要搬动的构件(即从第A层到第B层)整个放在第C层下面:"<<endl<<"如果C等于0,则要搬动的构件将放到最高层。"<<endl;
while(k--)
{
cin>>a>>b>>c;
MoveList_L(L,a,b,c);
}
PrintfList_L(L);
return 0;
}