数据结构报告3.docx
《数据结构报告3.docx》由会员分享,可在线阅读,更多相关《数据结构报告3.docx(34页珍藏版)》请在冰豆网上搜索。
![数据结构报告3.docx](https://file1.bdocx.com/fileroot1/2023-2/3/74a2bf36-afb1-4d5e-8cff-deaa43ae4008/74a2bf36-afb1-4d5e-8cff-deaa43ae40081.gif)
数据结构报告3
中南大学
数据结构实验报告
数据结构实验报告3
1.实验内容
图的操作算法
实现图的常用操作算法:
包括建立图的存储结构、深度优先搜索和广度优先搜索,求图的最小生成树、拓扑排序、最短路径等。
2.程序设计思路
1.最小生成树
Prim算法
设G=(V,E)是连通带权图,V={1,2,…,n}。
构造G的最小生成树Prim算法的基本思想是:
首先置S={1},然后,只要S是V的真子集,就进行如下的贪心选择:
选取满足条件i∈S,j∈V–S,且c[i][j]最小的边,将顶点j添加到S中。
这个过程一直进行到S=V时为止。
在这个过程中选取到的所有边恰好构成G的一棵最小生成树。
Kruskal算法
当图的边数为e时,Kruskal算法所需的时间是O(eloge)。
当e=Ω(n^2)时,Kruskal算法比Prim算法差;但当e=o(n^2)时,Kruskal算法比Prim算法好得多。
2.图的深度优先搜索
递归实现
(1)访问顶点v;visited[v]=1;//算法执行前visited[n]=0
(2)w=顶点v的第一个邻接点;
(3)while(w存在)
if(w未被访问)
从顶点w出发递归执行该算法;
w=顶点v的下一个邻接点;
非递归实现
(1)栈S初始化;visited[n]=0;
(2)访问顶点v;visited[v]=1;顶点v入栈S
(3)while(栈S非空)
x=栈S的顶元素(不出栈);
if(存在并找到未被访问的x的邻接点w)
访问w;visited[w]=1;
w进栈;
3.拓扑排序
(1)在AOV网络中选一个没有直接前驱的顶点,并输出之;
(2)从图中删去该顶点,同时删去所有它发出的有向边;
(3)重复以上步骤,直到全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;或者图中还有未输出的顶点,但已跳出处理循环。
这说明图中还剩下一些顶点,它们都有直接前驱,再也找不到没有前驱的顶点了。
这时AOV网络中必定存在有向环。
(拓扑排序完成;AOV网络中必定存在有向环)
4.了解了最短路径算法
单源最短路径问题:
已知有向带权图(简称有向网)G=(V,E),找出从某个源点s∈V到V中其余各顶点的最短路径。
迪杰斯特拉(Dijkstra)算法求单源最短路径。
3.主要算法
1、最小生成树
#include
#include
#include
#defineMAX_VERTEX_NUM20
#defineOK1
#defineERROR0
#defineMAX1000
usingnamespacestd;
typedefstructArcell
{
doubleadj;
}Arcell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{
charvexs[MAX_VERTEX_NUM];//节点数组
AdjMatrixarcs;//邻接矩阵
intvexnum,arcnum;//图的当前节点数和弧数
}MGraph;
typedefstructPnode//用于普利姆算法
{
charadjvex;//节点
doublelowcost;//权值
}Pnode,Closedge[MAX_VERTEX_NUM];//记录顶点集U到V-U的代价最小的边的辅助数组定义
typedefstructKnode//用于算法中存储一条边及其对应的2个节点
{
charch1;//节点1
charch2;//节点2
doublevalue;//权值
}Knode,Dgevalue[MAX_VERTEX_NUM];
intCreateUDG(MGraph&G,Dgevalue&dgevalue)//构造无向加权图的邻接矩阵
{
inti,j,k;
cout<<"请输入图中节点个数和边/弧的条数:
";
cin>>G.vexnum>>G.arcnum;
cout<<"请输入节点:
";
for(i=0;icin>>G.vexs[i];
for(i=0;i{
for(j=0;j{
G.arcs[i][j].adj=MAX;
}
}
cout<<"请输入一条边依附的定点及边的权值:
"<for(k=0;k{
cin>>dgevalue[k].ch1>>dgevalue[k].ch2>>dgevalue[k].value;
i=LocateVex(G,dgevalue[k].ch1);
j=LocateVex(G,dgevalue[k].ch2);
G.arcs[i][j].adj=dgevalue[k].value;
G.arcs[j][i].adj=G.arcs[i][j].adj;
}
returnOK;
}
intLocateVex(MGraphG,charch)//确定节点ch在图G.vexs中的位置
{
inta;
for(inti=0;i{
if(G.vexs[i]==ch)
a=i;
}
returna;
}
//typedefstructPnode//用于普利姆算法
//{
//charadjvex;//节点
//doublelowcost;//权值
//}Pnode,Closedge[MAX_VERTEX_NUM];//记录顶点集U到V-U的代价最小的边的辅助数组定义
voidMiniSpanTree_PRIM(MGraphG,charu)//普利姆算法求最小生成树
{
inti,j,k;
Closedgeclosedge;
k=LocateVex(G,u);
for(j=0;j{
if(j!
=k)
{
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
closedge[k].lowcost=0;
for(i=1;i{
k=Minimum(G,closedge);
cout<<"("<closedge[k].lowcost=0;
for(j=0;j{
if(G.arcs[k][j].adj{
closedge[j].adjvex=G.vexs[k];
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
}
}
intMinimum(MGraphG,Closedgeclosedge)//求closedge中权值最小的边,并返回其顶点在vexs中的位置
{
inti,j;
doublek=1000;
for(i=0;i{
if(closedge[i].lowcost!
=0&&closedge[i].lowcost{
k=closedge[i].lowcost;
j=i;
}
}
returnj;
}
voidMiniSpanTree_KRSL(MGraphG,Dgevalue&dgevalue)//克鲁斯卡尔算法求最小生成树
{
intp1,p2,i,j;
intbj[MAX_VERTEX_NUM];//标记数组
for(i=0;ibj[i]=i;
Sortdge(dgevalue,G);//将所有权值按从小到大排序
for(i=0;i{
p1=bj[LocateVex(G,dgevalue[i].ch1)];
p2=bj[LocateVex(G,dgevalue[i].ch2)];
if(p1!
=p2)
{
cout<<"("<for(j=0;j{
if(bj[j]==p2)
bj[j]=p1;
}
}
}
}
voidSortdge(Dgevalue&dgevalue,MGraphG)//对dgevalue中各元素按权值按从小到大排序
{
inti,j;
doubletemp;
charch1,ch2;
for(i=0;i{
for(j=i;j{
if(dgevalue[i].value>dgevalue[j].value)
{
temp=dgevalue[i].value;
dgevalue[i].value=dgevalue[j].value;
dgevalue[j].value=temp;
ch1=dgevalue[i].ch1;
dgevalue[i].ch1=dgevalue[j].ch1;
dgevalue[j].ch1=ch1;
ch2=dgevalue[i].ch2;
dgevalue[i].ch2=dgevalue[j].ch2;
dgevalue[j].ch2=ch2;
}
}
}
}
voidmain()
{
inti,j;
MGraphG;
charu;
Dgevaluedgevalue;
CreateUDG(G,dgevalue);
cout<<"图的邻接矩阵为:
"<for(i=0;i{
for(j=0;jcout<cout<}
cout<<"=============普利姆算法===============\n";
cout<<"请输入起始点:
";
cin>>u;
cout<<"构成最小代价生成树的边集为:
\n";
MiniSpanTree_PRIM(G,u);
cout<<"============克鲁斯科尔算法=============\n";
cout<<"构成最小代价生成树的边集为:
\n";
MiniSpanTree_KRSL(G,dgevalue);
}
2、拓扑排序
#include"stdio.h"
#defineMAX_VERTEX_NUM20
#include"conio.h"
#include"stdlib.h"
#defineSTACK_INIT_SIZE16
#defineSTACKINCREMENT5
typedefintSElemType;
typedefcharVertexType;
typedefstruct
{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;//我们依然用邻接表来作图的存储结构
typedefstructArcNode{
intadjvex;
structArcNode*nextarc;
intinfo;
}ArcNode;//表结点类型
typedefstructVNode{
VertexTypedata;
intcount;
ArcNode*firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];//头结点
typedefstruct{
AdjListvertices;//邻接表
intvexnum,arcnum;
}ALGraph;
intInitStack(SqStack&S)
{
S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
S.base)exit(-1);
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return1;
}//InitStack
intPush(SqStack&S,SElemTypee)
{
if((S.top-S.base)>=S.stacksize)
{
S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!
S.base)exit(-1);
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}//if
*(S.top)=e;
S.top++;
return1;
}//Push
intPop(SqStack&S,SElemType&e)
{
if(S.top==S.base)return0;
--S.top;
e=*S.top;
return1;
}//Pop
intStackEmpty(SqStack&S)
{
if(S.top==S.base)return1;
elsereturn0;
}//StackEmpty
intLocateVex(ALGraphG,charu)
{
inti;
for(i=0;i{if(u==G.vertices[i].data)returni;}
if(i==G.vexnum){printf("Erroru!
\n");exit
(1);}
return0;
}
voidCreateALGraph_adjlist(ALGraph&G)
{
inti,j,k,w;
charv1,v2,enter;
ArcNode*p;
printf("Inputvexnum&arcnum:
\n");
scanf("%d",&G.vexnum);
scanf("%d",&G.arcnum);
printf("InputVertices(以回车隔开各个数据):
\n");
for(i=0;i{scanf("%c%c",&enter,&G.vertices[i].data);//注意点,解说
G.vertices[i].firstarc=NULL;
}//for
printf("InputArcs(v1,v2,w)以回车分开各个数据:
\n");
for(k=0;k{
scanf("%c%c",&enter,&v1);
scanf("%c%c",&enter,&v2);
scanf("%d",&w);
i=LocateVex(G,v1);
j=LocateVex(G,v2);
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
p->info=w;
p->nextarc=G.vertices[i].firstarc;//前插法,即每次都插入到头结点的后面
G.vertices[i].firstarc=p;
printf("Next\n");
}//for
return;
}//CreateALGraph_adjlist
voidFindInDegree(ALGraph&G)
inti,j;
for(i=0;i{
G.vertices[i].count=0;
}//for
for(j=0;j{
//G.vertices[i].count++;
for(ArcNode*p=G.vertices[j].firstarc;p;p=p->nextarc)
G.vertices[p->adjvex].count++;
}//for
}//FindInDegree
intTopoSort(ALGraph&G)
{
SqStackS;
FindInDegree(G);
InitStack(S);
for(inti=0;iif(G.vertices[i].count==0)Push(S,i);
intcountt=0;
while(!
StackEmpty(S))
{
inti,m;
m=Pop(S,i);
printf("%c",G.vertices[i].data);++countt;
for(ArcNode*p=G.vertices[i].firstarc;p;p=p->nextarc)
{intk;
k=p->adjvex;
if(!
(--G.vertices[k].count))Push(S,k);
}//for
}//while
if(counttelsereturn1;
}//TopoSort
intmain()
{
ALGraphG;
CreateALGraph_adjlist(G);
TopoSort(G);
return1;
}
3、深度优先搜索和广度优先搜索
深度优先搜索:
图的深度优先遍历类似于树的前序遍历。
采用的搜索方法的特点是尽可能先对纵深方向进行搜索。
这种搜索方法称为深度优先搜索
广度优先搜索:
图的广度优先遍历BFS算法是一个分层搜索的过程,和树的层序遍历算法类同,它也需要一个队列以保持遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。
#include
#include
#include
#defineMAX_VERTEX_NUM20
typedefstructArcNode{
intadjvex;
structArcNode*nextarc;
//InfoType*info;
}ArcNode;
typedefstructLinkNode{
ArcNode*parc;//存储指针地址
structLinkNode*next;//指向一下个结点
}LinkNode;
typedefstructVNode{
charcData;//顶点元素值
ArcNode*firstarc;//指向第一条依附于该点的边
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct{
AdjListvertices;
intvexnum;//图的当前顶点数和弧数
intarcnum;
}ALGraph;
intVisited[MAX_VERTEX_NUM];
intPrintCheck(ALGraph*pag)
{
inti;
ArcNode*p;
printf("\nChecktheGraph!
\n");
printf("No\tdata\tnext\tnext\t.....\n");
for(i=0;ivexnum;i++)
{
printf("%d\t%c\t",i,pag->vertices[i].cData);
p=pag->vertices[i].firstarc;
while(p)
{
printf("%d\t",p->adjvex);
p=p->nextarc;
}
printf("\n");
}
return1;
}
intCreateGraph(ALGraph*pag,intstart,intend)
{
ArcNode*arcNodes=(ArcNode*)malloc(sizeof(ArcNode));
ArcNode*arcNodee=(ArcNode*)malloc(sizeof(ArcNode));
ArcNode*p;
if(!
arcNodes||!
arcNodee)return0;//从start->end生成关系
arcNodes->adjvex=end;//下一结点的位置
p=pag->vertices[start].firstarc;
if(!
p)//第一个结点单独构造
{
arcNodes->nextarc=pag->vertices[start].firstarc;
pag->vertices[start].firstarc=arcNodes;
}
else{
while(p->nextarc)p=p->nextarc;
p->nextarc=arcNodes;
arcNodes->nextarc=NULL;
}//end->start的关系生成
arcNodee->adjvex=start;//下一结点的位置
p=pag->vertices[end].firstarc;
if(!
p)//第一个结点单独构造
{
arcNodee->nextarc=pag->vertices[end].firstarc;
pag->vertices[end].firstarc=arcNodee;
}
else{
while(p->nextarc)p=p->nextarc;
p->nextarc=arcNodee;
arcNodee->nextarc=NULL;
}
return1;
}
voidDFSTraverse(ALGraphag,intstart)
{
LinkNode*Stack=(LinkNode*)mal