以邻接多重表为存储结构实现连通无向图的深度优先和广度优先遍历.docx
- 文档编号:9196996
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:24
- 大小:18.81KB
以邻接多重表为存储结构实现连通无向图的深度优先和广度优先遍历.docx
《以邻接多重表为存储结构实现连通无向图的深度优先和广度优先遍历.docx》由会员分享,可在线阅读,更多相关《以邻接多重表为存储结构实现连通无向图的深度优先和广度优先遍历.docx(24页珍藏版)》请在冰豆网上搜索。
以邻接多重表为存储结构实现连通无向图的深度优先和广度优先遍历
/*【基本要求】
以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和相应生成树的边集*/
//________头文件___________________________________________________________
#include<iostream>
using namespace std;
//_______无向图的邻接多重表存储表示p166____________________________________
const int NUM=20;
const int Data_Num=2;//每个顶点所表示的数据
typedef char VertexType[Data_Num];
/*
#define MAX_VERTEX_NUM 20
typedef struct emnu{int unvisited;int visited;} VisitIf;
typedef struct InfoType{};
typedef struct VertexType{};
*/
typedef struct EBox{
int mark; //访问标记
int ivex,jvex; //该边依附的2个顶点位置
struct EBox *ilink,*jlink; //分别指向依附这2个顶点的下一条边
//InfoType *info; //该边信息指针
}EBox;
typedef struct VexBox
{
VertexType data;
EBox *firstedge; //指向第一条依附该顶点的边
}VexBox;
typedef struct{
VexBox adjmulist[NUM];
int vexnum,edgenum; //无向图的当前顶点和边数
}AMLGraph;
//_________________________队列的定义_____________________________________
typedef int QElemType;
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front,rear;
}LinkQueue;
//_____________________寻找指定数据______________________________________________
//寻找输入的数据在图中的位置,若不存在则返回-1
int LocateVex(AMLGraph G,VertexType u)
{
int i;
for(i=0;i<G.vexnum;i++)
if(strcmp(u,G.adjmulist[i].data)==0)
return i;
return -1;
}
//________________________构造无向图_______________________________________________
//采用邻接多重表存储表示,构造无向图G
int CreateGraph(AMLGraph &G)
{
cout<<"请输入图的顶点数:
";
cin>>G.vexnum;//输入图当前的顶点数
cout<<"请输入图的弧数:
";
cin>>G.edgenum;//输入图当前的边数
cout<<"请输入每个顶点所对应的值:
"<<endl;
for(int i=0;i<G.vexnum;i++)
{
cin>>G.adjmulist[i].data;//输入顶点值
G.adjmulist[i].firstedge=NULL;//初始化指针
}
VertexType v1,v2;
EBox *p;
int j;//每条弧所关联的两个结点
for(int k=0;k<G.edgenum;k++)
{
cout<<"请输入第"<<k+1<<"弧的始点和终点:
";
cin>>v1;cin>>v2;
i=LocateVex(G,v1);j=LocateVex(G,v2);//确定v1和v2在图G中的位置
p=(EBox *)malloc(sizeof(EBox));
//对弧结点进行赋值
(*p).mark=0;
(*p).ivex=i;
(*p).jvex=j;
(*p).ilink=G.adjmulist[i].firstedge;
(*p).jlink=G.adjmulist[j].firstedge;
G.adjmulist[i].firstedge=G.adjmulist[j].firstedge=p;
}
return 1;
}
//返回V的值
VertexType* GetVex(AMLGraph G,int v)
{
if(v>G.vexnum||v<0)
exit(0);
return &G.adjmulist[v].data;
}
//返回V的第一个邻接点的序号,若没有则返回-1
int FirstAdjVex(AMLGraph G,VertexType v)
{
int i;
i=LocateVex(G,v);
if(i<0)
return -1;
if(G.adjmulist[i].firstedge)//V有邻接结点
if(G.adjmulist[i].firstedge->ivex==i)
return G.adjmulist[i].firstedge->jvex;
else
return G.adjmulist[i].firstedge->ivex;
else
return -1;
}
//返回V的(相对于W)的下一个邻接结点的序号,若W是V的最后一个邻接结点,则返回-1
int NextAdjVex(AMLGraph G,VertexType v,VertexType w)
{
int i,j;
EBox *p;
i=LocateVex(G,v);
j=LocateVex(G,w);
if(i<0||j<0)
return -1;
p=G.adjmulist[i].firstedge;
while(p)
if(p->ivex==i&&p->jvex!
=j)
p=p->ilink;
else if(p->jvex==i&&p->ivex!
=j)
p=p->jlink;
else
break;
if(p&&p->ivex==i&&p->jvex==j)
{
p=p->ilink;
if(p&&p->ivex==i)
return p->jvex;
else if(p&&p->jvex==i)
return p->jvex;
}
if(p&&p->ivex==j&&p->jvex==i)
{
p=p->jlink;
if(p&&p->ivex==i)
return p->jvex;
else if(p&&p->jvex==i)
return p->jvex;
}
return -1;
}
//__________________________队列的操作_________________________________________
int visite[NUM];//访问标志数组
int (*VisitFunc)(VertexType v);
void DFS(AMLGraph G,int v)
{
int j;
EBox *p;
VisitFunc(G.adjmulist[v].data);
visite[v]=1;//该顶点已经被访问
p=G.adjmulist[v].firstedge;
while(p)
{
j=p->ivex==vp->jvex:
p->ivex;
if(!
visite[j])
DFS(G,j);
p=p->ivex==vp->ilink:
p->jlink;
}
}
//________深度优先搜索_______________________________________________________
void DFSTraverse(AMLGraph G,int(*Visit)(VertexType))
{
int v,start;
VisitFunc=Visit;
for(v=0;v<G.vexnum;v++)
visite[v]=0;
cout<<"请输入你要开始进行查找的位置:
";
cin>>start;
cout<<"按广深度优先搜索的结果是:
"<<endl;
for(v=start;v<G.vexnum;v++)
{
if(v>=G.vexnum)
{
for(v=0;v<G.vexnum;v++)
{
if(!
visite[v])
DFS(G,v);
}//内层for
}//if
else
{
if(!
visite[v])
DFS(G,v);
}//else
}//外层for
cout<<"\b\b\b ";
cout<<endl;
}
//队列的初始化
int InitQueue(LinkQueue *Q)
{
(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));
if(!
(*Q).front)
exit(0);
(*Q).front->next=NULL;
return 1;
}
//判断队列是否为空,为空则返回1,否则返回0
int QueueEmpty(LinkQueue Q)
{
if(Q.front==Q.rear)
return 1;
else
return 0;
}
//向队列中插入元素
int EnQueue(LinkQueue *Q,QElemType e)
{
QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)
exit(0);
p->data=e;
p->next=NULL;
(*Q).rear->next=p;
(*Q).rear=p;
return 1;
}
//若队列不为空,则删除对头元素,并返回1;否则返回 0
int DeQueue(LinkQueue *Q,QElemType *e)
{
QueuePtr p;
if((*Q).front==(*Q).rear)
return 0;
p=(*Q).front->next;
*e=p->data;
(*Q).front->next=p->next;
if((*Q).rear==p)
(*Q).rear=(*Q).front;
free(p);
return 1;
}
/**
Boolean visited[MAX]; //访问标志数组
Status(*VisitFunc)(int v); //函数变量
void DFSTraverse(Graph G,Status(*Visit)(int v))
{ //对图G做深度优先遍历
VisitFunc=Visit //使用全局变量VisitFunc,使DFS不必设函数指针参数
for(v=0;v<G.vexnum;++v)visited[v]=FALSE; //访问标志数组初始化
for(v=0;v<G.vexnum;++v)
if(!
visited[v]) DFS(G,v); //对尚未访问的顶点调用DFS
}
void DFS(Graph G,int v)
{ //从第V个顶点出发递归地深度优先遍历图G
visited[v]=TRUE;VisitFunc(v);//访问第v个顶点
for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)
if(!
visited[w]) DFS(G,w);
}
**/
//_________广度优先搜索_____________________________________________________
//广度优先非递归遍历图G
void BFSTraverse(AMLGraph G,int(*Visit)(VertexType))
{
int u,v,w,start=0;
VertexType w1,u1;
LinkQueue Q;
for(v=0;v<G.vexnum;v++)
visite[v]=0;
InitQueue(&Q);
cout<<"请输入你要开始进行查找的位置:
";
cin>>start;
cout<<"按广度优先搜索的结果是:
"<<endl;
for(v=start;v<G.vexnum;v++)
{
if(!
visite[v])
{
visite[v]=1;
Visit(G.adjmulist[v].data);
EnQueue(&Q,v);//v入队列
while(!
QueueEmpty(Q))
{
DeQueue(&Q,&u);
strcpy(u1,*GetVex(G,u));
for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))
if(!
visite[w])
{
visite[w]=1;
Visit(G.adjmulist[w].data);
EnQueue(&Q,w);
}
}
}
}//for
InitQueue(&Q);
for(v=0;v<start;v++)
{
if(!
visite[v])
{
visite[v]=1;
Visit(G.adjmulist[v].data);
EnQueue(&Q,v);//v入队列
while(!
QueueEmpty(Q))
{
DeQueue(&Q,&u);
strcpy(u1,*GetVex(G,u));
for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))
if(!
visite[w])
{
visite[w]=1;
Visit(G.adjmulist[w].data);
EnQueue(&Q,w);
}
}
}
}//for
cout<<"\b\b\b ";
cout<<endl;
}
//把边的访问标记设置为0,即未被访问
void MarkUnVisited(AMLGraph G)
{
int i;
EBox *p;
for(i=0;i<G.vexnum;i++)
{
p=G.adjmulist[i].firstedge;
while(p)
{
p->mark=0;
if(p->ivex==i)
p=p->ilink;
else
p=p->jlink;
}
}
}
/**
void BFSTraverse(Graph G,Status(* visit)(int v)){
//按广度优先非递归遍历图G。
使用辅助队列Q和访问标志数组visited
for(v=0;v<G.vexnum;++v) visited[v]=FALSE;
InitQueue(Q) //置空的辅助队列Q
for(v=0;v<G.vexnum;++V)
if(!
visited[v]){ //v尚未访问
visited[v]=TRUE;Visit(v);
EnQueue(Q,v); //v入队列
while(!
QueueEmpty(Q)){
DeQueue(Q,v); //对头元素出队并置为u
for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))
if(!
Visited[w]){ //w为u的尚未访问的邻接顶点
Visited[w]=TRUE; Visit(w);
EnQueue(Q,W);
}//if
}//while
}//if
}//BFSTraverse
**/
//显示构造的无向图(包括定点数、顶点、边数、边)
void Display(AMLGraph G)
{
int i;
EBox *p;
MarkUnVisited(G);
cout<<G.vexnum<<"个顶点:
";
for(i=0;i<G.vexnum;i++)
cout<<G.adjmulist[i].data<<" ";
cout<<"; "<<G.edgenum<<"条边:
"<<endl;
for(i=0;i<G.vexnum;i++)
{
p=G.adjmulist[i].firstedge;
while(p)
if(p->ivex==i)
{
if(!
p->mark)
{
cout<<G.adjmulist[i].data<<"-->"<<G.adjmulist[p->jvex].data<<" ";
p->mark=1;//已经被访问过了
}
p=p->ilink;
}
else
{
if(!
p->mark)
{
cout<<G.adjmulist[p->ivex].data<<"-->"<<G.adjmulist[i].data<<" ";
p->mark=1;//已经被访问过了
}
p=p->jlink;
}
cout<<endl;
}
}
int Visit(VertexType v)
{
cout<<v<<"-->";
return 1;
}
//__________深度优先遍历下的节点访问序列___________________________________________
//__________广度优先遍历下的节点访问序列___________________________________________
//__________深度优先遍历生成树_____________________________________________________
//__________广度优先遍历生成树_____________________________________________________
//____________________________主函数______________________________________________
int main()
{int ch,YES=0;
AMLGraph g;
//____________________主界面_____________________________
cout<<"--------实验四 图遍历的演示----------------------------------------------"<<endl;
cout<<"基本要求:
"<<endl;
cout<<"以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。
---------"<<endl;
cout<<"以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和相应生成树的边集。
"<<endl;
cout<<"(1) 创建无向图-----------------------------------------------------------"<<endl;
cout<<"(2) 打印无向图-----------------------------------------------------------"<<endl;
cout<<"(3) 深度优先遍历并输出深度优先遍历下的节点访问序列-----------------------"<<endl;
cout<<"(4) 广度优先遍历并输出广度优先遍历下的节点访问序列-----------------------"<<endl;
//cout<<"(3) 输出深度优先遍历下的节点访问序列-------------------------------------"<<endl;
//cout<<"(4) 输出广度优先遍历下的节点访问序列-------------------------------------"<<endl;
cout<<"(5) 输出深度优先遍历生成树的边集-----------------------------------------"<<endl;
cout<<"(6) 输出广度优先遍历生成树的边集-----------------------------------------"<<endl;
cout<<"(7) ---------------------------------------------------------------------"<<endl;
cout<<"(8) ---------------------------------------------------------------------"<<endl;
cout<<"(9) 检查switch语句-------------------------------------------------------"<<endl;
cout<<"(0) 退出--------------------------------------
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 邻接 多重 存储 结构 实现 连通 深度 优先 广度 遍历