邻接矩阵的广度优先遍历

对《大话数据结构》P242-243——邻接矩阵的广度优先遍历,进行了自己的理解并完善了代码。

过程如下:先打印,再入队,再出队,再遍历与刚才出队元素相连并没有被访问过的点(入队之前先打印)
1、A入队,A出队,把与A相连并且没有被访问过的顶点B F依次入队
2、B出队,把与B相连并且没有被访问过的顶点C I G依次入队
3、F出队,把与F相连并且没有被访问过的顶点E入队
4、C出队,把与C相连并且没有被访问过的顶点D入队
5、I出队,把与I相连并且没有被访问过的顶点入队,发现没有,不入队
6、G出队,把与G相连并且没有被访问过的顶点H入队
7、E出队,把与E相连并且没有被访问过的顶点入队,发现没有,不入队
8、D出队,把与D相连并且没有被访问过的顶点入队,发现没有,不入队
9、H出队

举个简单的例子:

首先用邻接矩阵的存储结构创建该图,再进行广度优先遍历。

代码和解释如下(VS2012测试通过):

  1 #include <iostream>
  2 #include <stdlib.h>
  3 using namespace std;
  4 
  5 #define MAXVERTEX 6//定义顶点数最多为6
  6 #define MAXSIZE 6//循环队列的最大长度定义为6
  7 
  8 //图的邻接矩阵存储结构
  9 typedef struct
 10 {
 11     char vexs[MAXVERTEX];//本例6个顶点
 12     int arc[MAXVERTEX][MAXVERTEX];
 13     int numVertexes,numEdges;
 14 }MGraph;
 15 
 16 //邻接矩阵存储结构的创建
 17 MGraph *CreateMGraph(MGraph *G)
 18 {
 19     G=new MGraph;
 20     int i,j,k;
 21     cout<<"input numVertexes and numEdges"<<endl;
 22     cin>>G->numVertexes>>G->numEdges;//输入6 9,本例6个顶点,9条边
 23     cout<<"input numVertexes"<<endl;
 24     for(i=0;i<G->numVertexes;i++)
 25         cin>>G->vexs[i];//每次循环依次输入A B C D E F
 26     for(i=0;i<G->numVertexes;i++)
 27         for(j=0;j<G->numVertexes;j++)
 28             G->arc[i][j]=0;
 29     for(k=0;k<G->numEdges;k++)
 30     {
 31         cout<<"input vi and vj"<<endl; 
 32         cin>>i>>j;//每次循环依次输入0 1,0 3,0 5,1 2,1 3,1 5,2 3,3 4,4 5
 33         G->arc[i][j]=1;
 34         G->arc[j][i]=1;
 35     }
 36     return G;
 37 }
 38 
 39 //循环队列的顺序存储结构
 40 //保留一个元素空间,否则front==rear,是空队列还是满队列不容易判断
 41 typedef struct
 42 {
 43     char data[MAXSIZE];//队列,用数组形式表示  
 44     int front;//头序号,第一个元素的下标
 45     int rear;//尾序号,最后一个元素的下标
 46 }SqQueue;
 47 
 48 //循环队列的初始化,返回指向循环队列的地址
 49 SqQueue *InitQueue(SqQueue *Q)
 50 {
 51     Q=new SqQueue;
 52     Q->front=0;
 53     Q->rear=0;//初始化为空队列(front==rear为空队列)
 54     return Q;
 55 }
 56 
 57 //求循环队列的长度,返回循环队列的当前长度
 58 int QueueLength(SqQueue *Q)
 59 {
 60     return (Q->rear-Q->front+MAXSIZE)%MAXSIZE;
 61 }
 62 
 63 //循环队列的入队列操作
 64 void EnQueue(SqQueue *Q,char e)
 65 {
 66     if((Q->rear+1)%MAXSIZE==Q->front)//判断循环队列是否满
 67     {
 68         cout<<"error"<<" ";
 69         return;
 70     }
 71     Q->data[Q->rear]=e;//将元素e插入队尾
 72     Q->rear=(Q->rear+1)%MAXSIZE;//尾序号rear加1,若到最后转向头部
 73     cout<<e<<"in"<<" ";
 74     return;
 75 }
 76 
 77 //循环队列的出队列操作
 78 char DeQueue(SqQueue *Q)
 79 {
 80     char e;
 81     if(Q->front==Q->rear)//如果队列是否空
 82     {
 83         cout<<"error"<<" ";
 84         return 0;//返回0表示队列空,没有出队元素
 85     }
 86     e=Q->data[Q->front];
 87     Q->front=(Q->front+1)%MAXSIZE;//头序号front加1,若到最后转向头部
 88     cout<<e<<"out"<<" ";
 89     return e;
 90 }
 91 
 92 //邻接矩阵的广度遍历
 93 void BFSTraverse(MGraph *G)
 94 {
 95     int visited[MAXVERTEX];//标志顶点是否被访问,0是未被访问过,1是被访问过
 96     char e;
 97     
 98     SqQueue *s=NULL; 
 99     s=InitQueue(s);//初始化一个循环队列s,最大长度为MAXSIZE=6,初始为空
100 
101     for(int i=0;i<G->numVertexes;i++)//初始化所有顶点都未被访问过
102         visited[i]=0;
103     
104     for(int i=0;i<G->numVertexes;i++)//对于连通图,执行一次就可以遍历所有顶点
105     {
106         if(!visited[i])//如果没有被访问过,就处理,防止不必要的重复处理
107         {
108             visited[i]=1;//设置当前顶点访问过
109             cout<<"print1"<<G->vexs[i]<<" ";//打印该顶点
110             EnQueue(s,G->vexs[i]);//把该顶点入队
111             while(QueueLength(s))//若当前队列长度不等于0(即不为空)
112             {
113                 e=DeQueue(s);//元素出队,需要知道出队元素的下标,更新i
114                 switch (e)                    
115                 {
116                     case 'A':i=0;break;
117                     case 'B':i=1;break;
118                     case 'C':i=2;break;
119                     case 'D':i=3;break;
120                     case 'E':i=4;break;
121                     case 'F':i=5;break;
122                     default:break;
123                 }
124                 cout<<endl;
125                 //for循环寻找与刚才出队的顶点相连的并没有被访问过的顶点,如果找到该顶点,马上打印,并把找到的顶点入队
126                 for(int j=0;j<G->numVertexes;j++)//判断vexs[i]与其它顶点(包括自身)是否相连
127                 {
128                     if(G->arc[i][j]==1&&!visited[j])//如果与vexs[i]相连的顶点没有被访问过
129                     {
130                         visited[j]=1;//把找到的顶点设置为访问过
131                         cout<<"print2"<<G->vexs[j]<<" ";//打印该找到的顶点
132                         EnQueue(s,G->vexs[j]);//把找到的顶点入队
133                     }
134                 }
135             }
136         }
137     }
138 }
139 
140 int main(void)
141 {
142     MGraph *p=NULL;
143     p=CreateMGraph(p);//创建图
144     BFSTraverse(p);//广度遍历 
145 }

运行结果:

结果解释:

print1和print2用来标记在函数哪个部分打印,可以看出遍历顺序是ABDFCE。

也可以看出入队和出队的顺序。

打印A,A入队,A出队。

打印B,B入队;打印D,D入队;打印F,F入队。B出队。

打印C,C入队。D出队。

打印E,E入队。F出队。

C出队。

E出队。

转载于:https://www.cnblogs.com/hslzju/p/5409513.html

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值