图的遍历

来源:互联网 发布:网络00后女歌手名字 编辑:程序博客网 时间:2024/05/22 13:36
原博客地址:http://blog.chinaunix.net/uid-26833883-id-3171290.html
 
图的遍历是树的遍历的推广,是按照某种规则(或次序)访问图中各顶点依次且仅一次的操作,亦是将网络结构按某种规则线性化的过程。

 
由于图存在回路,为区别一顶点是否被访问过和避免顶点被多次访问,在遍历过程中,应记下每个访问过的顶点,即每个顶点对应有一个标志位,初始为False,一旦该顶点被访问,就将其置为True,以后若又碰到该顶点时,视其标志的状态,而决定是否对其访问。

对图的遍历通常有"深度优先搜索"和"广度优先搜索"方法,二者是人工智能的一个基础。

深度优先搜索(Depth First Search,简称DFS)

算法思路:

类似树的先根遍历。设初始化时,图中各顶点均未被访问,从图中某个顶点(设为V0)出发,访问V0,然后搜索V0的一个邻接点Vi,若Vi未被访问,则访问之,在 搜索Vi的一个邻接点(深度优先)...。若某顶点的邻接点全部访问完毕,则回溯(Backtracking)到它的上一顶点,然后再从此顶点又按深度优先的方法搜索下去,...,直到能访问的顶点都访问完毕为止。

设图G10如下图所示:

通过深度优先如下:

广度优先搜索(Breadth First Search),简称BFS

算法思路:

类似树的按层次遍历。初始时,图中各顶点均未被访问,从图中某顶点(V0)出发,访问V0,并依次访问V0的各邻接点(广度优先)。然后,分别从这些被访问过的顶点出发,扔仍按照广度优先的策略搜索其它顶点,....,直到能访问的顶点都访问完毕为止。

为控制广度优先的正确搜索,要用到队列技术,即访问完一个顶点后,让该顶点的序号进队。然后取相应队头(出队),考察访问过的顶点的各邻接点,将未访问过的邻接点访问 后再依次进队,...,直到队空为止。

通过广度优先如下:

查看代码如下:

queue.h

#ifndef QUEUE_H_#define QUEUE_H_#include <stdlib.h>typedef struct node{int data;struct node *next;}ListNode;typedef struct{ListNode *front;ListNode *rear;int     size;}Queue;//创建空队列Queue* create_empty_queue(){Queue* queue;queue = (Queue*)malloc(sizeof(Queue));if(queue!=NULL){queue->front = NULL;queue->rear = NULL;queue->size = 0;}return queue;}//判断队列是否为空int is_empty_queue(Queue* queue){if(queue->rear ==NULL && queue->front ==NULL && queue->size ==0)return 1;else return 0;}void EnQueue(Queue* queue,int data){ListNode* tmp;tmp = (ListNode*)malloc(sizeof(ListNode));tmp->data  =data;tmp->next =NULL;if(queue->front == NULL && queue->rear ==NULL){queue->front = tmp;queue->rear = tmp;}else{queue->rear->next = tmp;queue->rear = tmp;}queue->size++;}//出队//调用此函数之前要判空int DelQueue(Queue* queue){ListNode *tmp;int t;tmp = queue->front;queue->size--;if(queue->size==0){queue->front =NULL;queue->rear =NULL;}else{queue->front = queue->front->next;}t = tmp->data;free(tmp);return t;}void ClearQueue(Queue* queue){while(is_empty_queue(queue)!=1){ DelQueue(queue);//一个一个删除队列元素}}int GetSize(Queue *queue){return queue->size;}#endif

stack.h

#ifndef   STACK_H_#define   STACK_H_#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX 20//访问记录int visit[MAX];//图的结构设计typedef struct{int vex[MAX];//顶点int adjmatrix[MAX][MAX];//邻接矩阵int size;//顶点个数}GRAPH;//初始化图int init_graph(GRAPH** pg){memset((*pg),0,sizeof(GRAPH));(*pg)->size = 0;printf("input vex: \n");while(scanf("%d",&((*pg)->vex[(*pg)->size])))(*pg)->size++;while(getchar()!='\n');int i;for(i = 0; i < (*pg)->size; i++){printf("V%d ",(*pg)->vex[i]);}printf("\n");return 0;}int locatevex(GRAPH* pg, int  v){int i;for(i = 0; i < pg->size; i++){if(pg->vex[i] == v)//找到点vreturn i;}return 0;}int input_edge(GRAPH** pg){int v1,v2;GRAPH* p =*pg;int i,j;printf("input edge(i,j): \n");while(scanf("(%d,%d)",&v1,&v2))   //两个点确定一条边{getchar();i = locatevex(p,v1);j = locatevex(p,v2);p->adjmatrix[i][j] = p->adjmatrix[j][i] = 1;}#ifndef _DEBUG_int m,n;for(m = 0; m < p->size ; m++){for(n = 0; n < p->size; n++){printf("%d  ",p->adjmatrix[m][n]);}printf("\n");}#endifreturn 0;}//栈的设计typedef struct{int buf[MAX];int size;}stack;//创建空栈stack *create_empty_stack(){stack* st;st = (stack *)malloc(sizeof(stack));st->size = 0;return st;}//出栈int pop_stack(stack* st){int tmp;tmp = st->buf[--(st->size)];return tmp;}//入栈void push_stack(stack* st, int data){st->buf[st->size] = data;st->size++;}//判断空栈int is_empty_stack(stack* st){if(st->size == 0)return 1;elsereturn 0;}int visit_all(GRAPH * pg){int i=0;for(i = 0; i< pg->size; i++){if(visit[i] !=1)break;}if(i == pg->size)return 1;else return 0;}void clear_stack(stack* st){  if(st!=NULL)free(st);}#endif


test.c

#include "queue.h"#include "stack.h"//图像的深度非递归遍历void DFS(GRAPH* pg,int v){stack* st;int i;st = create_empty_stack();push_stack(st,pg->vex[v]);//将结点v人栈visit[v] =1;//访问过printf("V%d ",pg->vex[v]);while(!is_empty_stack(st)||!visit_all(pg))//要是栈不空或者还有结点没有访问{for(i =0; i < pg->size; i++){if(visit[i]== 0 &&pg->adjmatrix[v][i] ==1 )//如果结点v的邻接点没有被访问break;//且可通,找到这样的结点就退出循环}if(i == pg->size)//如果上一步循环没有找到这样的结点{v =  pop_stack(st);//栈顶元素出栈}else{v= i;visit[v] =1;push_stack(st,pg->vex[v]);printf("V%d ",pg->vex[v]);}}printf("\n");clear_stack(st);}//图的广度遍历void BFS(GRAPH*pg, int v){Queue* queue;queue = create_empty_queue();memset(&visit,0,sizeof(visit));int tmp;int i;EnQueue(queue,pg->vex[v]);//结点入栈visit[v] =1;//访问之while(is_empty_queue(queue)!=1){tmp = DelQueue(queue);//队首元素出队printf("V%d ",tmp);//打印之for(i= 0; i< pg->size; i++){if(pg->adjmatrix[tmp][i]==1 &&visit[i]==0)//如果通,并且没有访问过{EnQueue(queue,pg->vex[i]);visit[i] = 1;//访问之}}}printf("\n");}void main(){GRAPH* pg = (GRAPH*)malloc(sizeof(GRAPH));//int n;//输入顶点,初始化图init_graph(&pg);//初始化邻接矩阵input_edge(&pg);//图的深度优先遍历DFS(pg,0);//图的广度优先遍历BFS(pg,0);free(pg);}

程序运行结果:

 



原创粉丝点击