zoukankan      html  css  js  c++  java
  • 【转载】图的遍历

    【本文是转载的,转载来源: chengyaogen.blog.chinaunix.net 】
     
    图的遍历是树的遍历的推广,是按照某种规则(或次序)访问图中各顶点依次且仅一次的操作,亦是将网络结构按某种规则线性化的过程。

     
    由于图存在回路,为区别一顶点是否被访问过和避免顶点被多次访问,在遍历过程中,应记下每个访问过的顶点,即每个顶点对应有一个标志位,初始为False,一旦该顶点被访问,就将其置为True,以后若又碰到该顶点时,视其标志的状态,而决定是否对其访问。
     
    对图的遍历通常有"深度优先搜索"和"广度优先搜索"方法,二者是人工智能的一个基础。
     
    深度优先搜索(Depth First Search,简称DFS)
     
    算法思路:
     
    类似树的先根遍历。设初始化时,图中各顶点均未被访问,从图中某个顶点(设为V0)出发,访问V0,然后搜索V0的一个邻接点Vi,若Vi未被访问,则访问之,在 搜索Vi的一个邻接点(深度优先)...。若某顶点的邻接点全部访问完毕,则回溯(Backtracking)到它的上一顶点,然后再从此顶点又按深度优先的方法搜索下去,...,直到能访问的顶点都访问完毕为止。
     
    设图G10如下图所示:
     
    通过深度优先如下:
     
    广度优先搜索(Breadth First Search),简称BFS
     
    算法思路:
     
    类似树的按层次遍历。初始时,图中各顶点均未被访问,从图中某顶点(V0)出发,访问V0,并依次访问V0的各邻接点(广度优先)。然后,分别从这些被访问过的顶点出发,扔仍按照广度优先的策略搜索其它顶点,....,直到能访问的顶点都访问完毕为止。
     
    为控制广度优先的正确搜索,要用到队列技术,即访问完一个顶点后,让该顶点的序号进队。然后取相应队头(出队),考察访问过的顶点的各邻接点,将未访问过的邻接点访问 后再依次进队,...,直到队空为止。
     
    通过广度优先如下:
     
      1 //下面看一下实现代码:
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #define MAX 20
      6 //访问记录
      7 int visit[MAX];
      8 //图的结构设计
      9 typedef struct
     10 {
     11     int vex[MAX];//记录顶点
     12     int adjmatrix[MAX][MAX];//邻接矩阵
     13     int n;//顶点的个数
     14 }GRAPH;
     15 //初始化图
     16 int init_graph(GRAPH *pG)
     17 {
     18     memset(pG,0,sizeof(GRAPH));
     19     pG->n = -1;
     20     printf("input vex\n");
     21     while(scanf("%d",&pG->vex[++pG->n]));
     22     while(getchar() != '\n');
     23 #ifndef _DEBUG_
     24     int i = 0;
     25     for(i = 0;i < pG->n ;i ++)
     26     {
     27         printf("V%d ",pG->vex[i]);
     28     }
     29     printf("\n");    
     30 #endif
     31     
     32     return 0;
     33 }
     34 //获取顶点的位置
     35 int locatevex(GRAPH *pG,int vex)
     36 {
     37     int i = 0;
     38     for(i = 0;i < pG->n;i ++)
     39     {
     40         if(pG->vex[i] == vex )
     41             return i;
     42     }
     43     
     44     return 0;
     45 }
     46 //输入图的顶点之间的边
     47 int input_edge(GRAPH *pG)
     48 {
     49     int vex1,vex2;
     50     int i,j;
     51     printf("input edge(i,j):\n");
     52     //任意字母键结束
     53     while(scanf("(%d,%d)",&vex1,&vex2))
     54     {
     55         getchar();
     56         i = locatevex(pG,vex1);
     57         j = locatevex(pG,vex2);
     58         pG->adjmatrix[i][j] = pG->adjmatrix[j][i] = 1;
     59     }
     60 #ifndef _DEBUG_
     61     int m,n;
     62     for(m = 0;m < pG->n;m ++)
     63     {
     64         for(n = 0;n < pG->n; n ++)
     65         {
     66             printf("%d ",pG->adjmatrix[m][n]);
     67         }
     68         printf("\n");
     69     }
     70 #endif
     71     return 0;
     72 }
     73 //栈的设计
     74 typedef struct
     75 {
     76     int buf[MAX];
     77     int n;
     78 }Stack;
     79 //创建空栈
     80 Stack *create_empty_stack()
     81 {
     82     Stack *stack;
     83     stack = (Stack *)malloc(sizeof(Stack));
     84     stack->n = -1;
     85     return stack;
     86 }
     87 //出栈
     88 int pop_stack(Stack *stack)
     89 {
     90     int temp;
     91     temp = stack->buf[stack->n];
     92     stack->n --;
     93     return temp;
     94 }
     95 //入栈
     96 int push_stack(Stack *stack,int data)
     97 {
     98     stack->n ++;
     99     stack->buf[stack->n] = data;
    100     return 0;
    101 }
    102 //判断空栈
    103 int is_empty_stack(Stack *stack)
    104 {
    105     if(stack->n == -1)
    106         return 1;
    107     else
    108         return 0;
    109 }
    110 int visit_all(GRAPH *pG)
    111 {
    112     int i = 0;
    113     
    114     for(i = 0;i < pG->n; i ++)
    115     {
    116         if(visit[i] != 1)
    117             break;
    118     }
    119     if(i == pG->n)
    120         return 1;
    121     else
    122         return 0;
    123 }
    124 //图的深度非递归遍历
    125 int DFS(GRAPH *pG,int v)
    126 {
    127     Stack *stack;
    128     int i = 0;
    129     
    130     stack = create_empty_stack();
    131     push_stack(stack,pG->vex[v]);
    132     visit[v] = 1;
    133     printf("V%d ",pG->vex[v]);
    134     
    135     while(!is_empty_stack(stack) || !visit_all(pG))
    136     {
    137         for(i = 0;i < pG->n;i ++)
    138         {
    139             if(visit[i] == 0 && pG->adjmatrix[v][i] == 1)
    140                 break;
    141         }
    142         if(i == pG->n)
    143         {
    144             v = pop_stack(stack);
    145             
    146         }else{
    147         
    148             v = i;
    149             push_stack(stack,pG->vex[v]);
    150             visit[v] = 1;
    151             printf("V%d ",pG->vex[v]);
    152         }
    153     }
    154     printf("\n");
    155     return 0;
    156 }
    157 //队列的设计
    158 typedef struct node
    159 {
    160     int data;
    161     struct node *next;
    162     
    163 }ListNode;
    164 typedef struct
    165 {
    166     ListNode *front;
    167     ListNode *rear;
    168 }Queue;
    169 //创建空队列
    170 Queue *create_empty_queue()
    171 {
    172     Queue *queue;
    173     ListNode *head;
    174     queue = (Queue *)malloc(sizeof(Queue));
    175     head = (ListNode *)malloc(sizeof(ListNode));
    176     queue->front = queue->rear = head;
    177     return queue;
    178 }
    179 //判断队列是否为空
    180 int is_empty_queue(Queue *queue)
    181 {
    182     if(queue->rear == queue->front)
    183         return 1;
    184     else
    185         return 0;
    186 }
    187 //入队
    188 int EnterQueue(Queue *queue,int data)
    189 {
    190     ListNode *temp;
    191     temp = (ListNode *)malloc(sizeof(ListNode));
    192     temp->data = data;
    193     temp->next = NULL;
    194     queue->rear->next = temp;
    195     queue->rear = temp;
    196     return 0;
    197 }
    198 //出队
    199 int DelQueue(Queue *queue)
    200 {
    201     ListNode *temp;
    202     temp = queue->front;
    203     queue->front = queue->front->next;
    204     free(temp);
    205     temp = NULL;
    206     return queue->front->data;
    207 }
    208 //图的广度遍历
    209 int BFS(GRAPH *pG,int v)
    210 {
    211     Queue *queue = create_empty_queue();
    212     int i = 0;
    213     
    214     memset(&visit,0,sizeof(visit));
    215     EnterQueue(queue,v);
    216     visit[v] = 1;
    217     while(!is_empty_queue(queue))
    218     {
    219         v = DelQueue(queue);
    220         printf("V%d ",pG->vex[v]);
    221                 
    222         
    223         for(i = 0;i < pG->n;i ++)
    224         {
    225             if(visit[i] == 0 && pG->adjmatrix[v][i] == 1)
    226             {
    227                 EnterQueue(queue,i);
    228                 visit[i] = 1;
    229             }
    230         }
    231     }
    232     printf("\n");
    233     return 0;
    234 }
    235 int main()
    236 {
    237     GRAPH G;
    238     int n;
    239     //输入顶点,初始化图
    240     init_graph(&G);
    241     //初始化邻接矩阵
    242     input_edge(&G);
    243     //图的深度遍历
    244     DFS(&G, 0);
    245     //图的广度遍历
    246     BFS(&G,0);
    247     
    248     return 0;
    249 }
     
    输出结果:
     
     
  • 相关阅读:
    宋体、新宋体、仿宋体
    单例模式————你就是我的唯一
    极乐净土代码——第一辑
    泛函是个什么概念
    http和https的区别
    get和post的区别
    浏览器输入URL按回车后都经历了什么?
    求两个列表的交集、并集、差集
    使用lamdba函数对list排序
    乐观锁和悲观锁的区别
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/Graph.html
Copyright © 2011-2022 走看看