实验五 图基本操作的实现.docx
《实验五 图基本操作的实现.docx》由会员分享,可在线阅读,更多相关《实验五 图基本操作的实现.docx(22页珍藏版)》请在冰豆网上搜索。
实验五图基本操作的实现
实验五图基本操作的实现
【实验课程名称】数据结构
【实验项目名称】单链表基本操作的实现
【实验目的】
1理解图的存储结构;
2掌握邻接矩阵储存结构的图基本操作;
3学会设计实验数据验证程序。
【实验仪器及环境】计算机,windowxp操作系统,VC++6.0
【实验内容及步骤】
1.图的基本操作
constINFINITY=INT_MAX; //最大值∞
constMAX_VERTEX_NUM=20; //最大顶点个数
typedefenum{DG,DN,AG,AN}GraphKind;
//类型标志{有向图,有向网,无向图,无向网}
typedefstructArcCell{ //弧的定义
VRTypeadj; //VRType是顶点关系类型。
对无权图,用1或0
//表示相邻否;对带权图,则为权值类型。
InfoType*info; //该弧相关信息的指针
}AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct{ //图的定义
VertexTypevexs[MAX_VERTEX_NUM];//顶点信息
AdjMatrixarcs; //表示顶点之间关系的二维数组
intvexnum,arcnum; //图的当前顶点数和弧(边)数
GraphKindkind; //图的种类标志
2.实现的基本操作:
CreateGraph(&G,V,VR);
初始条件:
V是图的顶点集,VR是图中弧的集合。
操作结果:
按V和VR的定义构造图G。
DesstroyGraph(&G);
初始条件:
图G存在。
操作结果:
销毁图G。
LocateVex(G,u);
初始条件:
图G存在,u和G中顶点有相同特征。
操作结果:
若G中存在和u相同的顶点,则返回该顶点在图中位置;
否则返回其它信息。
GetVex(G,v);
初始条件:
图G存在,v是G中某个顶点。
操作结果:
返回v的值。
FirstAdjVex(G,v);
初始条件:
图G存在,v是G中某个顶点。
操作结果:
返回v的第一个邻接点。
若该顶点在G中没有邻接点,
则返回"空"。
NextAdjVex(G,v,w);
初始条件:
图G存在,v是G中某个顶点,w是v的邻接顶点。
操作结果:
返回v的(相对于w的)下一个邻接点。
若w是v的最后一个邻接点,则返回"空"。
PutVex(&G,v,value);
初始条件:
图G存在,v是G中某个顶点。
操作结果:
对v赋值value。
InsertVex(&G,v);
初始条件:
图G存在,v和图中顶点有相同特征。
操作结果:
在图G中增添新顶点v。
DeleteVex(&G,v);
初始条件:
图G存在,v是G中某个顶点。
操作结果:
删除G中顶点v及其相关的弧。
InsertArc(&G,v,w);
初始条件:
图G存在,v和w是G中两个顶点。
操作结果:
在G中增添弧,若G是无向的,则还增添对称弧。
DeleteArc(&G,v,w);
初始条件:
图G存在,v和w是G中两个顶点。
操作结果:
在G中删除弧,若G是无向的,则还删除对称弧。
DFSTraverse(G,Visit());
初始条件:
图G存在,Visit是顶点的应用函数。
操作结果:
对图G进行深度优先遍历。
遍历过程中对每个顶点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
BFSTraverse(G,Visit());
初始条件:
图G存在,Visit是顶点的应用函数。
操作结果:
对图G进行广度优先遍历。
遍历过程中对每个顶点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
基本操作的代码:
#include
#include
usingnamespacestd;
#defineint_max10000
#defineinf9999
#definemax20
//…………………………………………邻接矩阵定义……………………
typedefstructArcCell{
intadj;
char*info;
}ArcCell,AdjMatrix[20][20];
typedefstruct{
charvexs[20];
AdjMatrixarcs;
intvexnum,arcnum;//有向图的当前顶点数和弧数
}MGraph_L;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
intlocalvex(MGraph_LG,charv){//返回V的位置
inti=0;
while(G.vexs[i]!
=v){
++i;
}
returni;
}
intcreatMGraph_L(MGraph_L&G){//创建图用邻接矩阵表示
charv1,v2;
inti,j,w;
cout<<"…………创建无向图…………"<(46)不包括“()”"<cin>>G.vexnum>>G.arcnum;
for(i=0;i!
=G.vexnum;++i){
cout<<"输入顶点"<
cin>>G.vexs[i];
}
for(i=0;i!
=G.vexnum;++i)
for(j=0;j!
=G.vexnum;++j){
G.arcs[i][j].adj=int_max;
G.arcs[i][j].info=NULL;
}
for(intk=0;k!
=G.arcnum;++k){
cout<<"输入一条边依附的顶点和权:
(ab3)不包括“()”"<cin>>v1>>v2>>w;//输入一条边依附的两点及权值
i=localvex(G,v1);//确定顶点V1和V2在图中的位置
j=localvex(G,v2);
G.arcs[i][j].adj=w;
G.arcs[j][i].adj=w;
}
cout<<"图G邻接矩阵创建成功!
"<returnG.vexnum;
}
voidljjzprint(MGraph_LG){
inti,j;
for(i=0;i!
=G.vexnum;++i){
for(j=0;j!
=G.vexnum;++j)
cout<cout<}
}
intvisited[max];//访问标记
intwe;
typedefstructarcnode{//弧结点
intadjvex;//该弧指向的顶点的位置
structarcnode*nextarc;//弧尾相同的下一条弧
char*info;//该弧信息
}arcnode;
typedefstructvnode{//邻接链表顶点头接点
chardata;//结点信息
arcnode*firstarc;//指向第一条依附该结点的弧的指针
}vnode,adjlist;
typedefstruct{//图的定义
adjlistvertices[max];
intvexnum,arcnum;
intkind;
}algraph;
//…………………………………………队列定义……………………
typedefstructqnode{
intdata;
structqnode*next;
}qnode,*queueptr;
typedefstruct{
queueptrfront;
queueptrrear;
}linkqueue;
//………………………………………………………………………
typedefstructacr{
intpre;//弧的一结点
intbak;//弧另一结点
intweight;//弧的权
}edg;
intcreatadj(algraph&gra,MGraph_LG){//用邻接表存储图
inti=0,j=0;
arcnode*arc,*tem,*p;
for(i=0;i!
=G.vexnum;++i){
gra.vertices[i].data=G.vexs[i];
gra.vertices[i].firstarc=NULL;
}
for(i=0;i!
=G.vexnum;++i){
for(j=0;j!
=G.vexnum;++j){
if(gra.vertices[i].firstarc==NULL){
if(G.arcs[i][j].adj!
=int_max&&j!
=G.vexnum){
arc=(arcnode*)malloc(sizeof(arcnode));
arc->adjvex=j;
gra.vertices[i].firstarc=arc;
arc->nextarc=NULL;
p=arc;
++j;
while(G.arcs[i][j].adj!
=int_max&&j!
=G.vexnum){
tem=(arcnode*)malloc(sizeof(arcnode));
tem->adjvex=j;
gra.vertices[i].firstarc=tem;
tem->nextarc=arc;
arc=tem;
++j;
}
--j;
}
}
else{
if(G.arcs[i][j].adj!
=int_max&&j!
=G.vexnum){
arc=(arcnode*)malloc(sizeof(arcnode));
arc->adjvex=j;
p->nextarc=arc;
arc->nextarc=NULL;
p=arc;
}
}
}
}
gra.vexnum=G.vexnum;
gra.arcnum=G.arcnum;
cout<<"图G邻接表创建成功!
"<return1;
}
voidadjprint(algraphgra){
inti;
for(i=0;i!
=gra.vexnum;++i){
arcnode*p;
cout<
p=gra.vertices[i].firstarc;
while(p!
=NULL){
cout<adjvex;
p=p->nextarc;
}
cout<}
}
intfirstadjvex(algraphgra,vnodev){//返回依附顶点V的第一个点
//即以V为尾的第一个结点
if(v.firstarc!
=NULL)
returnv.firstarc->adjvex;
}
intnextadjvex(algraphgra,vnodev,intw){//返回依附顶点V的相对于W的下一个顶点
arcnode*p;
p=v.firstarc;
while(p!
=NULL&&p->adjvex!
=w){
p=p->nextarc;
}
if(p->adjvex==w&&p->nextarc!
=NULL){
p=p->nextarc;
returnp->adjvex;
}
if(p->adjvex==w&&p->nextarc==NULL)
return-10;
}
intinitqueue(linkqueue&q){//初始化队列
q.rear=(queueptr)malloc(sizeof(qnode));
q.front=q.rear;
if(!
q.front)
return0;
q.front->next=NULL;
return1;
}
intenqueue(linkqueue&q,inte){//入队
queueptrp;
p=(queueptr)malloc(sizeof(qnode));
if(!
p)
return0;
p->data=e;
p->next=NULL;
q.rear->next=p;
q.rear=p;
return1;
}
intdequeue(linkqueue&q,int&e){//出队
queueptrp;
if(q.front==q.rear)
return0;
p=q.front->next;
e=p->data;
q.front->next=p->next;
if(q.rear==p)
q.rear=q.front;
free(p);
return1;
}
intqueueempty(linkqueueq){//判断队为空
if(q.front==q.rear)
return1;
return0;
}
voidbfstra(algraphgra)//广度优先遍历
{
inti,e;
linkqueueq;
for(i=0;i!
=gra.vexnum;++i)
visited[i]=0;
initqueue(q);
for(i=0;i!
=gra.vexnum;++i)
if(!
visited[i])
{visited[i]=1;
cout<enqueue(q,i);
while(!
queueempty(q))
{
dequeue(q,e);
//cout<<""<for(we=firstadjvex(gra,gra.vertices[e]);we>=0;we=nextadjvex(gra,gra.vertices[e],we))
{
if(!
visited[we])
{
visited[we]=1;
cout<enqueue(q,we);
}
}
}
}
}
intdfs(algraphgra,inti);//声明DFS
intdfstra(algraphgra)
{
inti,j;
for(i=0;i!
=gra.vexnum;++i)
{
visited[i]=0;
}
for(j=0;j!
=gra.vexnum;++j)
{
if(visited[j]==0)
dfs(gra,j);
}
return0;
}
intdfs(algraphgra,inti)
{
visited[i]=1;
intwe1;
//cout<
cout<//cout<for(we=firstadjvex(gra,gra.vertices[i]);we>=0;we=nextadjvex(gra,gra.vertices[i],we))
{
//cout<we1=we;
//cout<if(visited[we]==0)
//cout<<
dfs(gra,we);//<//cout<
we=we1;
//cout<}
return12;
}
intbfstra_fen(algraphgra)//求连通分量
{
inti,j;
for(i=0;i!
=gra.vexnum;++i)
{
visited[i]=0;
}
for(j=0;j!
=gra.vexnum;++j)
{
if(visited[j]==0)
{
dfs(gra,j);
cout<}
}
return0;
}
typedefstruct{
intadjvex;
intlowcost;
}closedge;
intprim(intg[][max],intn)//最小生成树PRIM算法
{
intlowcost[max],prevex[max];//LOWCOST[]存储当前集合U分别到剩余结点的最短路径
//prevex[]存储最短路径在U中的结点
inti,j,k,min;
for(i=2;i<=n;i++)//n个顶点,n-1条边
{
lowcost[i]=g[1][i];//初始化
prevex[i]=1;//顶点未加入到最小生成树中
}
lowcost[1]=0;//标志顶点1加入U集合
for(i=2;i<=n;i++)//形成n-1条边的生成树
{
min=inf;
k=0;
for(j=2;j<=n;j++)//寻找满足边的一个顶点在U,另一个顶点在V的最小边
if((lowcost[j]=0))
{
min=lowcost[j];
k=j;
}
printf("(%d,%d)%d\t",prevex[k]-1,k-1,min);
lowcost[k]=0;//顶点k加入U
for(j=2;j<=n;j++)//修改由顶点k到其他顶点边的权值
if(g[k][j]{
lowcost[j]=g[k][j];
prevex[j]=k;
}
printf("\n");
}
return0;
}
intacrvisited[100];//kruscal弧标记数组
intfind(intacrvisited[],intf)
{
while(acrvisited[f]>0)
f=acrvisited[f];
returnf;
}
voidkruscal_arc(MGraph_LG,algraphgra)
{
edgedgs[20];
inti,j,k=0;
for(i=0;i!
=G.vexnum;++i)
for(j=i;j!
=G.vexnum;++j)
{
if(G.arcs[i][j].adj!
=10000)
{
edgs[k].pre=i;
edgs[k].bak=j;
edgs[k].weight=G.arcs[i][j].adj;
++k;
}
}
intx,y,m,n;
intbuf,edf;
for(i=0;i!
=gra.arcnum;++i)
acrvisited[i]=0;
for(j=0;j!
=G.arcnum;++j)
{
m=10000;
for(i=0;i!
=G.arcnum;++i)
{
if(edgs[i].weight{
m=edgs[i].weight;
x=edgs[i].pre;
y=edgs[i].bak;
n=i;
}
}
//cout<//cout<buf=find(acrvisited,x);
edf=find(acrvisited,y);
//cout<edgs[n].weight=10000;
if(buf!
=edf)
{
acrvisited[buf]=edf;
cout<<"("<cout<}
}
}
voidmain()
{
algraphgra;
MGraph_LG;
inti,d,g[20][20];
chara='a';
d=creatMGraph_L(G);
creatadj(gra,G);
vnodev;
cout<若该图为非强连通图(含有多个连通分量)时"<<<"最小生成树不存在,则显示为非法值。
"<cout<<"…………………菜单……………………"<cout<<"0、显示该图的邻接矩阵……………………"<cout<<"1、显示该图的邻接表……………………"<cout<<"2、深度优先遍历…………………………"<cout<<"3、广度优先遍历…………………………"<cout<<"4、最小生成树PRIM算法…………………"<cout<<"5、最小生成树KRUSCAL算法………………"<cout<<"6、该图的连通分量………………………"<ints;
chary='y';
while(y='y')
{
cout<<"请选择菜单:
"<cin>>s;
switch(s)
{
case0:
cout<<"邻接矩阵显示如下:
"<ljjzprint(G);
break;
case1:
cout<<"邻接表显示如下:
"<adjprint(gra);
break;
case2:
cout<<"广度优先遍历:
";
bfstra(gra);
cout<break;
case3:
for(i=0;i!
=gra.vexnum;++i)
{
visited[i]=0;
}
cout<<"深度优先遍历:
";
d