zoukankan      html  css  js  c++  java
  • 图的广度优先搜索

    1.概述
    为了实现图的广度优先搜索,必须引入队列结构来保存已访问过的顶点序列:即从指定的顶点开始,每访问一个顶点就同时使该顶点进入队尾;然后由队头取出一个顶点并访问该顶点的所有未被访问过的邻接边结点并且使该邻接边结点进入队尾......如此进行下去直到队空为止,则图中所有由开始顶点所能到达的全部顶点均已访问过。
    参考代码:
      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #define MAXSIZE 30
      4 
      5 typedef struct node1//邻接表结点
      6 {
      7     int adjvex;//邻接点域
      8     struct node1 *next;//指向下一个邻接边结点的指针域
      9 }EdgeNode;//邻接表结点类型
     10 
     11 typedef struct vnode//顶点表结点
     12 {
     13     int vertex;//顶点域
     14     EdgeNode *firstedge;//指向邻接表的第一个邻接结点的指针域
     15 }VertexNode;//顶点表结点类型
     16 
     17 void CreatAdjlist(VertexNode g[],int e,int n)//建立无向图的邻接表,n为顶点数,e为边数,g[]存储n个顶点表结点
     18 {
     19     EdgeNode *p;
     20     int i,j,k;
     21     printf("Input data of veter(0~n-1);
    ");
     22     for(i=0;i<n;i++)//建立有n个顶点的顶点表
     23     {
     24         g[i].vertex=i;//读入顶点信息
     25         g[i].firstedge=NULL;//初始化指向顶点i的邻接表表头指针
     26     }
     27     for(k=1;k<=e;k++)//输入e条边
     28     {
     29         printf("Input edge of(i,j):");
     30         scanf("%d,%d",&i,&j);
     31         p=(EdgeNode*)malloc(sizeof(EdgeNode));
     32         p->adjvex=j;//在顶点Vi的邻接表中添加邻接点为j的结点
     33         p->next=g[i].firstedge;//插入是在邻接表表头进行的
     34         g[i].firstedge=p;
     35         p=(EdgeNode*)malloc(sizeof(EdgeNode));
     36         p->adjvex=i;//在顶点Vj的邻接表中添加邻接点为i的结点
     37         p->next=g[j].firstedge;//插入是在邻接表表头进行的
     38         g[j].firstedge=p;
     39     }
     40 }
     41 
     42 typedef struct node
     43 {
     44     int data;
     45     struct node *next;
     46 }QNode;//链队列结点的类型
     47 
     48 typedef struct
     49 {
     50     QNode *front,*rear;//将头、尾指针纳入到一个结构体的链队列
     51 }LQueue;//链队列类型
     52 
     53 void Init_LQueue(LQueue **q)//创建一个带头结点的空队列
     54 {
     55     QNode *p;
     56     *q=(LQueue*)malloc(sizeof(LQueue));//申请带头、尾指针的链队列
     57     p=(QNode*)malloc(sizeof(QNode));//申请链队列的头结点
     58     p->next=NULL;//头结点的next指针置为空
     59     (*q)->front=p;//队头指针指向头结点
     60     (*q)->rear=p;//队尾指针指向头结点
     61 }
     62 
     63 int Empty_LQueue(LQueue *q)//判断队是否为空
     64 {
     65     if(q->front==q->rear)//队为空
     66         return 1;
     67     else
     68         return 0;
     69 }
     70 
     71 
     72 void In_LQueue(LQueue *q,int x)//入队
     73 {
     74     QNode *p;
     75     p=(QNode *)malloc(sizeof(QNode));//申请新链队列结点
     76     p->data=x;
     77     p->next=NULL;//新结点作为队尾结点时其next域为空
     78     q->rear->next=p;//将新结点*p链到原队尾结点之后
     79     q->rear=p;//使队尾指针指向新的队尾结点*p
     80 }
     81 
     82 void Out_LQueue(LQueue *q,int *x)//出队
     83 {
     84     QNode *p;
     85     if(Empty_LQueue(q))
     86         printf("Queue is empty!
    ");//队空出队失败
     87     else
     88     {
     89         p=q->front->next;//指针p指向链队列第一个数据结点(即队头结点
     90         q->front->next=p->next;//头结点的next指针指向链队列的第二个数据结点(即删除第一个数据结点)
     91         *x=p->data;//将删除的队头结点数据由x返回
     92         free(p);
     93         if(q->front->next==NULL)//出队后若队为空则置为空队列
     94             q->rear=q->front;
     95     }
     96 }
     97 
     98 int visited[MAXSIZE];//MAXSIZE为大于或等于无向图顶点个数的常量
     99 void BFS(VertexNode g[],LQueue *Q,int i)//广度优先搜索遍历邻接表存储的图,g为顶点表,Q为队指针,i为第i个顶点
    100 {
    101     int j,*x=&j;//出队顶点将由指针x传给j
    102     EdgeNode *p;
    103     printf("%4d",g[i].vertex);//输出顶点i信息,即访问顶点i
    104     visited[i]=1;//置顶点i为访问过标志
    105     In_LQueue(Q,i);//顶点i入队Q
    106     while(!Empty_LQueue(Q))//当队Q非空时
    107     {
    108         Out_LQueue(Q,x);//队头顶点出队经由指针x送给就j(暂计为顶点j)
    109         p=g[j].firstedge;//根据顶点j的表头指针查找其邻接表的第一个邻接边结点
    110         while(p!=NULL)//当邻接边结点非空时
    111         {
    112             if(!visited[p->adjvex])//输出这个邻接边结点的顶点信息
    113             {
    114             printf("%4d",g[p->adjvex].vertex);//输出这个邻接边结点的顶点信息
    115             visited[p->adjvex]=1;//置该邻边结点为访问过的标志
    116             In_LQueue(Q,p->adjvex);//将该邻接边结点送入队列Q   
    117             }
    118         p=p->next;//在顶点j的邻接表中查找j的下一个邻接边结点
    119         }
    120     }
    121 }
    122 
    123 void main()
    124 {
    125     int e,n;
    126     VertexNode g[MAXSIZE];//定义顶点表结点类型的数组g
    127     LQueue *q;
    128     printf("Input number of node:
    ");//输入图中结点的个数
    129     scanf("%d",&n);
    130     printf("Input number of edge:
    ");//输入图中边的个数
    131     scanf("%d",&e);
    132     printf("Make adjlist:
    ");
    133     CreatAdjlist(g,e,n);//建立无向图的链接表
    134     Init_LQueue(&q);//队列q初始化
    135     printf("BFSTraverse:
    ");
    136     BFS(g,q,0);//广度优先遍历以邻接表存储的无向图
    137     printf("
    ");
    138 }

    说明:


    遍历邻接边和图具体如下:


    出入队顺序:

  • 相关阅读:
    [清华集训2016]温暖会指引我们前行——LCT+最大生成树
    BZOJ1415[Noi2005]聪聪和可可——记忆化搜索+期望dp
    NOIP2018游记
    BZOJ4832[Lydsy1704月赛]抵制克苏恩——期望DP
    BZOJ1906树上的蚂蚁&BZOJ3700发展城市——RMQ求LCA+树链的交
    BZOJ2822[AHOI2012]树屋阶梯——卡特兰数+高精度
    BZOJ4001[TJOI2015]概率论——卡特兰数
    BZOJ1805[Ioi2007]Sail船帆——线段树+贪心
    [IOI2018]排座位——线段树
    BZOJ3718[PA2014]Parking——树状数组
  • 原文地址:https://www.cnblogs.com/wxdjss/p/5498451.html
Copyright © 2011-2022 走看看