【转载】图的遍历
【本文是转载的,转载来源: 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 }
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net