- 主要内容:
使用邻接表来实现图的存储,编写以下算法:
(1)图的创建
(2)深度优先遍历
(3)广度优先遍历
(4)完善main()函数的编写,调用以上算法,验证算法的正确性
- 代码模拟实现:
#include<iostream>
using namespace std;
#define null 0
#define MvNum 100 //最大顶点数
typedef struct ArcNode//边结点
{
int adjvex;//该边所指向的顶点位置
struct ArcNode *nextarc;//指向下一条边结点
} ArcNode;
typedef struct VNode{//顶点信息
char data;
ArcNode *fistarc;//指向第一条依附该顶点的边结点指针
}VNode,AdjList[MvNum];
typedef struct
{
AdjList vertices;//顶点信息数组
int vexnum,arcnum;//图的顶点数和边数
}ALGraph;
typedef struct{
int base[MvNum];//存放编号
int front,rear;//头指针,尾指针
}SqQueue;//队列
int Locatevex(ALGraph &G,char v)//获取顶点在该图中的编号,编号从零开始
{
for(int i=0;i<G.vexnum;i++)
{
if(G.vertices[i].data==v)
{
return i;
}
}
}
void CreateGraph(ALGraph &G)//用邻接表实现无向图的创建
{
cout<<"请输入该图的总顶点数和总边数"<<endl;
cin>>G.vexnum>>G.arcnum;
cout<<"请输入顶点信息(后面编号从零开始)"<<endl;
for(int i=0;i<G.vexnum;i++)
{
cin>>G.vertices[i].data;
G.vertices[i].fistarc=null;//初始化置零
}
cout<<"请输入边的两个相关顶点"<<endl;
for(int k=0;k<G.arcnum;k++)
{
char vi,vj;
cin>>vi;//输入该边的两个相关的顶点
cin>>vj;
int i=Locatevex(G,vi);//获取两顶点在该图中的编号
int j=Locatevex(G,vj);//编号从零开始
ArcNode *p1=new ArcNode;
p1->adjvex=j;//vi的邻接点边编号为j
p1->nextarc=G.vertices[i].fistarc;//头接法,把p1插在顶点vi头部
G.vertices[i].fistarc=p1;
ArcNode *p2=new ArcNode;
p2->adjvex=i;//vj的邻接点边编号为i
p2->nextarc=G.vertices[j].fistarc;//头接法,把p2插在顶点vj头部
G.vertices[j].fistarc=p2;
}
}
bool visited[MvNum]={false};//DFS的访问数组
void DFS_AL(ALGraph &G,int v)//DFS_深度优先搜索遍历,从v编号顶点开始
{
cout<<v<<" ";
visited[v]=true;//访问编号为v的顶点
ArcNode *p=G.vertices[v].fistarc;//p指向编号为v顶点的第一个边结点
while(p!=null)
{
int w=p->adjvex;//w为编号为v顶点的邻结点
if(!visited[w])//若w未被访问,递归调用DFS_AL访问
{
DFS_AL(G,w);
}
p=p->nextarc;//移向编号为v顶点的下一个邻接点
}
}
bool visited2[MvNum]={false};//BFS的访问数组
void InitQueue(SqQueue &Q)//初始化队列
{
Q.front=Q.rear=0;
}
void EnQueue(SqQueue &Q,int v)
{
Q.base[Q.rear]=v;
Q.rear=(Q.rear+1)%MvNum;
}
void DeQueue(SqQueue &Q,int &u)
{
u=Q.base[Q.front];
Q.front=(Q.front+1)%MvNum;
}
bool QueueEmpty(SqQueue &Q)//判断是否队空
{
if(Q.front==Q.rear)
{
return true;
}
return false;
}
void BFS(ALGraph G,int v)
{ ArcNode *p;
int u,w;
SqQueue Q;
cout<<v<<" ";
visited2[v]=true;
InitQueue(Q);//初始化队列
EnQueue(Q,v);//v入队
while(!QueueEmpty(Q))
{
DeQueue(Q,u);//队头元素出队,并赋值给u
p=G.vertices[u].fistarc;//p指向u顶点的第一个边结点
while(p)
{
w=p->adjvex;//w为p指向的边结点的编号
if(!visited2[w])//未访问则访问,反之,不访问
{
cout<<w<<" ";
visited2[w]=true;
}
EnQueue(Q,w);//w入队
p=p->nextarc;//指向下一个边结点
}
}
cout<<endl<<endl<<endl;
}
void Menu(ALGraph &G)//通过switch语句来实现菜单功能
{ int x=0;
cout<<"------------欢迎来到主菜单------------"<<endl;
cout<<"请输入对应数字来实现想使用的功能:"<<endl;
cout<<"----1.图的创建"<<endl;
cout<<"----2.深度优先搜索遍历"<<endl;
cout<<"----3.广度优先搜索遍历"<<endl;
cout<<"----4.退出----"<<endl;
cin>>x;
switch(x)
{ case 1:
CreateGraph(G);//创建无向图
Menu(G);
case 2:
cout<<"深度优先搜索遍历DFS:";
DFS_AL(G,0); //从编号为0的顶点开始
cout<<endl<<endl<<endl;
visited[MvNum]={false};//重新赋值
Menu(G);
case 3:
cout<<"广度优先搜索遍历BFS:";
BFS(G,0);//从编号为0的顶点开始
visited2[MvNum]={false};//重新赋值
Menu(G);
case 4:
exit(0);//退出程序
default:
cout<<"Error 请重试~"<<endl;
Menu(G);
}
}
int main()
{ ALGraph G;
Menu(G);//主菜单
return 0;
}
- 测试运行结果: