1.深度优先遍历是连通图的一种遍历策略.其基本思想如下:
设x是当前被访问的顶点,在对x做过访问的标记之后,选择一条从x出发的未检测过的边(x,y),若发现顶点y已经访问过了,则重新选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过,然后从y开始搜索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检测的边,直到从x出发的所有的边都已经检测过为止;
2.广度优先搜索:广度优先搜索是一种遍历策略;从一个顶点出发,辐射状地优先遍历其周围较广的区域,例如,从图的某个顶点vo出发,并访问此节点.然后依次访问v0的各个未曾访问的邻接点w1,w2,w3...,然后依次从w1,w2..出发访问各自未被访问的邻接点.重复此步骤,直到所有的顶点都被访问.
上面是两种遍历图的基本思想,用我写的代码来看具体的过程中:如图:
如上图:节点ABCDEFG,我们就给每个顶点依次编号1,2,3,4,5,6;(在这里,我们就以无向图来说)
首先,我们输入节点个数和关系的个数,然后依次ABCDEFG,并用相应的的结构存储它,然后输入每个节点之间的关系:AB,AC,AD,DF,DG,BE,EG,FG,CF,BD;用邻接表存储它;存储后的示意图:
1 A:2,3,4 ; 2 B:1,4,5 ; 3 C:1,6 ; 4 E:2,7; 5 F:3,4,7; 6 G:4,5,6
下面是我实现的图的建立,dfs递归和非递归,以及bfs遍历:
************************************************************************* > File Name: linjiebiao.c > Author:yang > Mail:yanglongfei@xiyoulinux.org > Created Time: 2015年11月26日 星期四 22时38分28秒 ************************************************************************/ #include<stdio.h> #include<stdlib.h> #define MAXVEX 20 typedef struct Stack { int data; struct Stack *next; }LinkStack; typedef struct Queue { int data; struct Queue *next; }LNode; typedef struct { LNode *front; LNode *rear; }LinkQueue; typedef struct ArcNode { int adjvex; struct ArcNode *next; }ArcNode; typedef struct VertexNode { char vexdata; ArcNode *head; }VertexNode; typedef struct { VertexNode vertex[MAXVEX]; int vexnum; //顶点数 int arcnum; //边数 }AdjList; /********************************栈的操作******************************************/ LinkStack *Init_LinkStack(LinkStack *T) { T=(LinkStack *)malloc(sizeof(LinkStack)); T->next=NULL; return T; } int IsEmpty_LinkStack(LinkStack *T) { if(T->next!=NULL){ return 0; } return 1; } LinkStack* Push_LinkStack(LinkStack *T,int t) { LinkStack *s=(LinkStack *)malloc(sizeof(LinkStack)); if(s==NULL){ return NULL; } s->data=t; s->next=T->next; T->next=s; } LinkStack *Pop_LinkStack(LinkStack *T,int *t) { LinkStack *p=T->next; if(T->next==NULL){ return NULL; } *t=p->data; T->next=p->next; free(p); } /*************************队列的操作****************************/ LinkQueue *Init_LinkQueue() { LinkQueue *q=(LinkQueue *)malloc(sizeof(LinkQueue)); LNode *p=(LNode *)malloc(sizeof(LNode)); p->next=NULL; q->front=q->rear=p; return q; } int IsEmpty_LinkQueue(LinkQueue *q) { if(q->front == q->rear){ return 1; } return 0; } void EnterQueue(LinkQueue *q,int t) { LNode *s=(LNode *)malloc(sizeof(LNode)); s->data=t; s->next=NULL; q->rear->next=s; q->rear=s; } int OutQueue(LinkQueue *q,int *t) { LNode *p; if(IsEmpty_LinkQueue(q)){ printf("the Queue is Empty!\n"); return 0; }else{ p=q->front->next; *t=p->data; q->front->next=p->next; free(p); if(q->front->next==NULL){ q->rear=q->front; } return 1; } } VertexNode *Insert(VertexNode *h,ArcNode *p) //此函数的意义是把每个链表根据adjvex的按从小到大的顺序排列; { ArcNode *pre,*cur,*q; cur=h->head; if(cur == NULL){ p->next=cur; cur->next=p; }else{ pre =h->head; q=h->head->next; while(q){ if(p->adjvex < q->adjvex ){ p->next=q; pre->next=p; break; } pre = q; q=q->next; } if(q == NULL){ //当新的节点比当前链表中的所有的adjvex都大时,直接插在链表的最后面. p->next==NULL; pre->next = p; } } return h; } AdjList *Created_Graph(AdjList *G) { int i,j,k,n1,n2; ArcNode *s; char vex1,vex2; G=(AdjList *)malloc(sizeof(AdjList)); printf("请输入顶点的个数和边数:"); scanf("%d%d",&G->vexnum,&G->arcnum); printf("请输入顶点:\n"); for(i=1;i<=G->vexnum;i++) { printf("No.%d号顶点的值:",i); scanf(" %c",&G->vertex[i].vexdata); G->vertex[i].head=(ArcNode *)malloc(sizeof(ArcNode)); //为每个头节点开辟空间;有头节点的链表; G->vertex[i].head->next=NULL; //头节点指向为空; } printf("请输入由两个顶点构成的边:"); for(k=1;k<=G->arcnum;k++){ scanf(" %c%c",&vex1,&vex2); for(i=1;i<=G->vexnum;i++){ if(G->vertex[i].vexdata == vex1){ n1=i; } if(G->vertex[i].vexdata == vex2){ n2=i; } } s=(ArcNode *)malloc(sizeof(ArcNode)); s->adjvex = n2; Insert(&G->vertex[n1],s); /*如果是有向图,则下面的语句去掉就行*/ s=(ArcNode *)malloc(sizeof(ArcNode)); s->adjvex = n1; Insert(&G->vertex[n2],s); } return G; } int visited[MAXVEX]={0}; void dfs(AdjList *G,int i) { ArcNode *p; printf("%c ",G->vertex[i].vexdata); visited[i]=1; p=G->vertex[i].head->next; while(p){ if(visited[p->adjvex]==0){ dfs(G,p->adjvex); } p=p->next; } } void trans_dfs(AdjList *G) { int v; for(v=1;v<=G->vexnum;v++){ visited[v]=0; } for(v=1;v<=G->vexnum;v++){ if(visited[v]==0){ dfs(G,v); //当图只有一个连通分量时,此句只会执行一次; } } } void undfs(AdjList *G,int vo) { LinkStack *T; ArcNode *p; T=Init_LinkStack(T); int visited[MAXVEX]={0},i, t; Push_LinkStack(T,vo); while(!IsEmpty_LinkStack(T)){ Pop_LinkStack(T,&t); if(visited[t]==0){ printf("%c ",G->vertex[t].vexdata); visited[t]=1; } p=G->vertex[t].head->next; while(p){ if(visited[p->adjvex] == 0){ printf("%c ",G->vertex[p->adjvex].vexdata); visited[p->adjvex]=1; Push_LinkStack(T,p->adjvex); p=G->vertex[p->adjvex].head->next; }else{ p=p->next; } } } //for(i=1;i<=G->vexnum;i++){} } void bfs(AdjList *G,int v) { int i,t; ArcNode *p; LinkQueue *S=Init_LinkQueue(); for(i=1;i<=G->vexnum;i++) { visited[i]=0; } visited[v]=1; printf("%c ",G->vertex[v].vexdata); EnterQueue(S,v); while(!IsEmpty_LinkQueue(S)){ OutQueue(S,&t); p=G->vertex[t].head->next; while(p){ if(visited[p->adjvex]==0){ printf("%c ",G->vertex[p->adjvex].vexdata); visited[p->adjvex]=1; EnterQueue(S,p->adjvex); } p=p->next; } } } void print(AdjList *G) { ArcNode *p; int i; for(i=1;i<=G->vexnum;i++){ printf(" %c:",G->vertex[i].vexdata); p=G->vertex[i].head->next; while(p) { printf("%d ",p->adjvex); p=p->next; } printf("\n"); } } int main(int argc,char *argv[]) { AdjList *G; G=Created_Graph(G); print(G); printf("**************dfs递归遍历*****************************\n"); dfs(G,1); printf("\n"); printf("*************dfs递归遍历多个连通分量********************\n"); trans_dfs(G); printf("\n"); printf("*******************dfs非递归遍历*************************\n"); undfs(G,1); printf("\n"); printf("*********************bfs遍历****************************\n"); bfs(G,1); printf("\n"); return 0; }