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 }
     
    输出结果:
     
     
  • 相关阅读:
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    使用Jasmine和karma对传统js进行单元测试
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    nginx 基于IP的多虚拟主机配置
    Shiro 框架的MD5加密算法实现原理
    项目实战:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)
    实用技巧:阿里云服务器建立公网物联网服务器(解决阿里云服务器端口,公网连接不上的问题)
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/Graph.html
Copyright © 2011-2022 走看看