数据结构实验.docx
《数据结构实验.docx》由会员分享,可在线阅读,更多相关《数据结构实验.docx(22页珍藏版)》请在冰豆网上搜索。
数据结构实验
武汉工程大学
计算机科学与工程学院
《算法与数据结构》实验报告
专业班级
10智能01班
实验地点
201
学生学号
1005030134
指导教师
吕品
学生姓名
谢红涛
实验时间
实验项目
实验2非线性结构综合应用
实验类别
操作性()验证性()设计性()综合性(√)其它()
实验目的及要求
1.加深理解树和图的非线性结构特点;
2.灵活运用树和图的存储结构、二叉树的遍历技术、图的拓扑排序等来解决有关应用问题;
3.加深递归程序设计的训练;
4.注重提高关于模型选择、算法设计和分析方面的能力。
成绩评定表
类别
评分标准
分值
得分
合计
上机表现
积极出勤、遵守纪律
主动完成实验设计任务
30分
程序代码
比较规范、基本正确
功能达到实验要求
30分
实验报告
及时递交、填写规范
内容完整、体现收获
40分
说明:
评阅教师:
日期:
2012年月日
实验内容
1.二叉树的前序,中序与后序遍历的非递归算法。
(必做)
算法的描述:
结点要入两次栈,出两次栈;为了区别同一个结点的两次出栈,设置标志flag,当结点进、出栈时,其标志flag也同时进、出栈。
1.栈s初始化;
2.循环直到root为空且栈s为空
2.1当root非空时循环
2.1.1将root连同标志flag=1入栈;
2.1.2继续遍历root的左子树;
2.2当栈s非空且栈顶元素的标志为2时,出栈并输出栈顶结点;
2.3若栈非空,将栈顶元素的标志改为2,准备遍历栈顶结点的右子树;
核心程序代码:
#include//后序遍历非递归算法
#include
#include
usingnamespacestd;
structtree
{
chardata;
structtree*lchild;
structtree*rchild;
};
typedefstructtree*treptr;
treptrbuild(treptrt)//先序建树
{
charc;
c=getchar();
if(c=='#')
{
t=NULL;
}
else
{
t=(treptr)malloc(sizeof(structtree));
t->data=c;
t->lchild=build(t->lchild);
t->rchild=build(t->rchild);
}
returnt;
}
structstack
{
treptr*top,*base;
};
typedefstructstack*stackptr;
voidinit(stackptrs)//初始化栈
{
s->base=(treptr*)malloc(sizeof(treptr)*100);
s->top=s->base;
}
voidpush(stackptrs,treptrt)//入栈
{
*(s->top++)=t;
}
treptrpop(stackptrs)//弹出栈顶元素
{
treptrt;
t=*(--(s->top));
returnt;
}
treptrgettop(stackptrs)//取栈顶元素
{
treptr*l=s->top-1;
return*(l);
}
voidpostorder(treptrt)//这是非递归后序实现
{
stackptrs=(stackptr)malloc(sizeof(structstack));
treptrtemp=t;
treptrp;
treptrlastvist=NULL;
init(s);
p=t;
while(p||s->top!
=s->base)
{
while(p)
{
push(s,p);
p=p->lchild;
}
temp=gettop(s);
if(temp->rchild==NULL||temp->rchild==lastvist)
{
putchar(temp->data);
lastvist=pop(s);
}
else
p=temp->rchild;
}
}
intmain()
{
cout<<"请输入这颗二叉树(以##表示该节点无子树,并最终以#表示输入完毕):
"<treptrt=NULL;
t=build(t);
printf("非递归后序遍历\n");
postorder(t);
printf("\n");
return0;
}
给出随意构造的二叉树,以其为实验目标
初始界面,提示输入一个二叉树,根据图示,以及输入规则,这里输入回车后,即出现后序遍历的序列:
DEBFCA
如下图所示:
遇到的问题及解决办法:
2.任意给定一个有向图,设计一个算法,对它进行拓扑排序。
(必做)
算法的描述:
1.栈S初始化;累加器count初始化;
2.扫描顶点表,将没有前驱(即入度为0)的顶点压栈;
3.当栈S非空时循环
3.1vj=退出栈顶元素;输出vj;累加器加1;
3.2将顶点vj的各个邻接点的入度减1;
3.3将新的入度为0的顶点入栈;
4.if(count
核心程序代码:
#include
usingnamespacestd;
#definemaxsize50
structnode
{
intadjvex;
node*next;
};
structgraph
{
intvexter;
intin;
node*firstedge;
};
typedefstruct
{
int*base;
int*top;
intstacksize;
}sqstack;
voidinitstack(sqstack&S)
{
S.base=(int*)malloc(sizeof(int));
S.top=S.base;
S.stacksize=maxsize+1;
}
voidcreateadlist(graphinDegree[],intn,inte)//创建邻接链表
{
inti,k,j;
node*q;
for(i=1;i<=n;i++)
{
inDegree[i].vexter=i;
inDegree[i].in=0;
inDegree[i].firstedge=NULL;
}
for(k=1;k<=e;k++)
{
cout<<"请输入第"<\n";
cout<<"从";
cin>>i;
cout<<"邻接到";
cin>>j;
cout<<'\n';
inDegree[j].in++;
q=(node*)malloc(sizeof(structnode));
q->adjvex=j;
q->next=inDegree[i].firstedge;
inDegree[i].firstedge=q;
}
}
voidTopoSort(graphinDegree[],intn)
{
inti,v,count=0;
sqstackS;
node*p;
initstack(S);
for(i=1;i<=n;i++)
if(inDegree[i].in==0)
*S.top++=i;
while(S.top!
=S.base)
{
v=*--S.top;
cout<count++;
p=inDegree[v].firstedge;
while(p!
=NULL)
{
inDegree[p->adjvex].in--;
if(inDegree[p->adjvex].in==0)
*S.top++=p->adjvex;
p=p->next;
}
}cout<if(countelsecout<<"无回路"<}
voidmain()
{
graphinDegree[maxsize];
intv,e;
cout<<"该AOV网的顶点数:
";
cin>>v;
cout<<"该AOV网的边条数:
";
cin>>e;
createadlist(inDegree,v,e);
cout<<"拓扑排序序列为:
"<TopoSort(inDegree,v);
}
实验结果:
首先给出此次实验结果所用的AOV网图示:
(1)初始界面,提示输入AOV网的定点数及边数,根据以上图示,这里输入5和6,显示如下:
(2)再提示输入各个边,从第一条边到第六条边的邻接序列,即从X邻接到Y,根据图示,这里分别是从1邻接到2、从1邻接到3、从2邻接到3、从3邻接到5、从3邻接到4、从5邻接到4这六条边,将其分别输入,得以下图示:
系统计算出AOV网的拓扑排序序列,输出了12354,即图示拓扑网络的拓扑排序序列,并提示无回路。
若某个网,有回路,则不会输出拓扑序列,并输出“有回路”。
遇到的问题及解决办法:
3.任意给定一个AOE网,设计一个算法求其关键路径。
(选做)
算法的描述:
核心程序代码:
遇到的问题及解决办法:
4火车车厢重排
算法的描述:
1.分别对k个队列初始化;
2.初始化下一个要输出的车厢编号nowOut=1;
3.依次取入轨中的每一个车厢的编号;
3.1如果入轨中的车厢编号等于nowOut,则
3.1.1输出该车厢;
3.1.2nowOut++;
3.2否则,考察每一个缓冲轨队列
for(j=1;j<=k;j++)
3.2.1取队列j的队头元素c;
3.2.2如果c=nowOut,则
3.2.2.1将队列j的队头元素出队并输出;
3.2.2.2nowOut++;
3.3如果入轨和缓冲轨的队头元素没有编号为nowOut的车厢,则
3.3.1求小于入轨中第一个车厢编号的最大队尾元素所在队列编号j;
3.3.2如果j存在,则把入轨中的第一个车厢移至缓冲轨j;
3.3.2如果j不存在,但有多于一个空缓冲轨,则把入轨中的第一个车厢移至一个空缓冲轨;否则车厢无法重排,算法结束;
核心程序代码:
#include
#include
usingnamespacestd;
constintQueueSize=1000;
template
structNode
{
Tdata;
Node*next;
};
template
classLinkQueue //链队列模板类
{
public:
LinkQueue(); //构造函数
~LinkQueue(); //析构函数
voidTrans(); //遍历缓冲轨
voidEnQueue(Tx);//入队
TDeQueue(); //出队
TGetFront() //查找队头元素
{if(front!
=rear)returnfront->next->data;}
TGetRear() //查找队尾元素
{if(front!
=rear)returnrear->data;}
boolEmpty(){front==NULL?
return1:
return0;} //判断队空
friendvoidTrainPermute(intarr[],LinkQueuea[],intn,intk);
private:
Node*front,*rear;
};
template
LinkQueue:
:
LinkQueue()
{
Node*s=newNode;
s->next=NULL;
front=rear=s;
}
template
LinkQueue:
:
~LinkQueue()
{
Node*p=front;
while(p!
=NULL)
{
Node*q=p;
p=p->next;
deleteq;
}
}
template
voidLinkQueue:
:
EnQueue(Tx)
{
Node*s=newNode;
s->data=x;
s->next=NULL;
rear->next=s;
rear=s;
}
template
TLinkQueue:
:
DeQueue()
{
if(rear==front)throw"下溢";
Node*p=front->next;
intx=p->data;
front->next=p->next;
if(p->next==NULL)
rear=front;
deletep;
returnx;
}
template
voidLinkQueue:
:
Trans()
{Node*p=front->next;
while(p)
{
cout<data<<'';
p=p->next;
};
}
voidmain()
{
try
{
intn,k,t;
cout<<"请输入火车车厢数n(n请小于1000):
\nn=";
cin>>n;
cout<<"请输入缓冲轨数k:
\nk=";
cin>>k;
cout<<"系统将对"<\n";
if(n>1000)throw"输入错误!
车厢数必须小于1000!
";
if(n<=0)throw"输入错误!
车厢数必须大于0!
";
if(k<=0)throw"输入错误!
缓冲轨数必须大于0!
";
srand((unsigned)time(NULL));
intcount=0;
int*array;
array=newint[n];
int*ifmark;
ifmark=newint[n];
while(count!
=n)
{
t=rand()%n;
if(ifmark[t]!
=1)
{
array[t]=count+1;
ifmark[t]=1;
count++;
}
}
cout<<"火车车厢入轨顺序为:
"< for(inti=0;i cout< cout< LinkQueue*buffer;
buffer=newLinkQueue[k];
TrainPermute(array,buffer,n,k);
cout< }
catch(char*s)
{
cout<
}
}
voidTrainPermute(intarr[],LinkQueuea[],intn,intk)
{
inti=0;
boolaa=1;
while((i {
aa=0; //亮点:
与非门思想!
for(intm=0;m {
if(a[m].GetRear() {
a[m].EnQueue(arr[i]);
i++;
aa=1;
break;
}
if(a[m].front->next==NULL)
{
a[m].EnQueue(arr[i]);
aa=1;
i++;
break;
}
}
}
if(aa==0) //当无法将入轨中队头车厢移至合适缓冲轨中时,程序结束
{
cout<<"车厢无法重排,算法结束"< }
else //当入轨中已经没有车厢时
{
for(intm=0;m {
cout<<"第"<<(m+1)<<"个缓冲轨的列车编号";
a[m].Trans();
cout< }
cout<<"火车车厢出轨顺序为:
"< for(intnewOut=1;newOut<=n;newOut++)
{
for(intj=0;j {
if(a[j].GetFront()==newOut)
{
cout< } } } }}
实验结果:
(1)初始界面,提示输入火车车厢数n(n请小于1000)
(2)这里取车厢数为9,缓冲轨道数为3,和实验指导书上的一致,按回车后,系统对9个数字随机排列并入轨,自动输出入轨顺序(这里随机生成为672814359),并分别显示1、2、3号缓冲轨上的列车编号,最后输出出轨顺序(9个车厢,所以这里是123456789),程序结束,提示Pressanykeytocontinue.
遇到的问题及解决办法:
5稀疏矩阵的转置
算法的描述:
1.设置转置后矩阵B的行数、列数和非零元素的个数;
2.计算A中每一列的非零元素个数;
3.计算A中每一列的第一个非零元素在B中的下标;
4.依次取A中的每一个非零元素对应的三元组;
2.1确定该元素在B中的下标pb;
2.2将该元素的行号列号交换后存入B中pb的位置;
2.3预置该元素所在列的下一个元素的存放位置;
核心程序代码:
#include
#include
usingnamespacestd;
constintQueueSize=1000;
template
structNode
{
Tdata;
Node*next;
};
template
classLinkQueue //链队列模板类
{
public:
LinkQueue(); //构造函数
~LinkQueue(); //析构函数
voidTrans(); //遍历缓冲轨
voidEnQueue(Tx);//入队
TDeQueue(); //出队
TGetFront() //查找队头元素
{if(front!
=rear)returnfront->next->data;}
TGetRear() //查找队尾元素
{if(front!
=rear)returnrear->data;}
boolEmpty(){front==NULL?
return1:
return0;} //判断队空
friendvoidTrainPermute(intarr[],LinkQueuea[],intn,intk);
private:
Node*front,*rear;
};
template
LinkQueue:
:
LinkQueue()
{
Node*s=newNode;
s->next=NULL;
front=rear=s;
}
template
LinkQueue:
:
~LinkQueue()
{
Node*p=front;
while(p!
=NULL)
{
Node*q=p;
p=p->next;
deleteq;
}
}
template
voidLinkQueue:
:
EnQueue(Tx)
{
Node*s=newNode;
s->data=x;
s->next=NULL;
rear->next=s;
rear=s;
}
template
TLinkQueue:
:
DeQueue()
{
if(rear==front)throw"下溢";
Node*p=front->next;
intx=p->data;
front->next=p->next;
if(p->next==NULL)
rear=front;
deletep;
returnx;
}
template
voidLinkQueue:
:
Trans()
{Node*p=front->next;
while(p)
{
cout<data<<'';
p=p->next;
};
}
voidmain()
{
try
{
intn,k,t;
cout<<"请输入火车车厢数n(n请小于1000):
\nn=";
cin>>n;
cout<<"请输入缓冲轨数k:
\nk=";
cin>>k;
cout<<"系统将对"<\n";
if(n>1000)throw"输入错误!
车厢数必须小于1000!
";
if(n<=0)throw"输入错误!
车厢数必须大于0!
";
if(k<=0)throw"输入错误!
缓冲轨数必须大于0!
";
srand((unsigned)time(NULL));
intcoun