图的邻接表创建及深度优先遍历和广度优先遍历
最近在学图,写个笔记。 图的创建一般有邻接矩阵和邻接表两种方法,邻接矩阵对于边数相对于顶点较少的图会有极大的浪费,所以用邻接表,用数组与链表相配合 顶点用一维数组储存 所有顶点的邻接点构成一个线性表,因为邻接点的个数不确定,所以用单链表 图的深度优先搜索是对先序遍历的推广 一个递归的过程,沿着一个方向遍历,一直到最后,然后再回来到另一个结点沿着一个方向。 广度优先遍历就是一层一层的遍历。如上图 上代码:
#include<stdio.h> #include<stdlib.h> #define MAXVEX 7 //代表最大顶点数 #define INFINITY 65535 //代表无穷大 typedef struct GraphNode { int index; //下标 struct GraphNode *next; //指向下一个的指针 }GraphNode; typedef struct Gra { char c; //顶点元素 GraphNode *first ; }Gra; typedef struct Graph { Gra vex[MAXVEX]; int numvex,edge; //顶点元素和边的数量 }Graph; //创建一个队列,用来广度优先遍历 typedef struct QNode { int data; struct QNode *next; }QNode,*Queueprt; typedef struct { Queueprt front,rear; }LinkQueue; //队列的初始化 void InitQueue(LinkQueue *q) { q->front=q->rear=(Queueprt)malloc(sizeof(QNode)); q->front->next=NULL; } //入队列 void EnQueue(LinkQueue *q,int e) { Queueprt p; p=(Queueprt)malloc(sizeof(QNode)); p->data=e; q->rear->next=p; p->next=NULL; q->rear=p; } //出队列 void DeQueue(LinkQueue *q,int *e) { if(q->front==q->rear) { return; } Queueprt p; p=q->front->next; *e = p->data; q->front->next=p->next; if(p==q->rear) { q->rear=q->front; } free(p); } //判断队列是否为空 int QueueEmpty(LinkQueue *q) { if(q->front==q->rear) { return 1; } else { return 0; } } //创建图 void create(Graph *g) { int i,j,m,n; GraphNode *p,*q; printf("输入顶点元素的数量和边的数量: "); scanf("%d %d",&(g->numvex),&(g->edge)); printf("输入顶点元素: "); for(i=0;i<g->numvex;i++) { getchar(); scanf("%c",&(g->vex[i].c) ); g->vex[i].first=NULL; } //建立边集 printf("输入边两边顶点的下标: "); for(j=0;j<g->edge;j++) { scanf("%d %d",&m,&n); p=(GraphNode *)malloc(sizeof(GraphNode)); p->index=m; p->next=g->vex[n].first; g->vex[n].first=p; //这里是把first移到p q=(GraphNode *)malloc(sizeof(GraphNode)); q->index=n; q->next=g->vex[m].first; g->vex[m].first=q; } } void print(Graph *g) { int i; GraphNode *p; for(i=0;i<g->numvex;i++) { p=g->vex[i].first; while(p) { printf("(%c,%c)",g->vex[i].c,g->vex[p->index].c); p=p->next; } printf(" "); } } //DFS遍历 void DFS(Graph *g,int i,int *visited) { GraphNode *p; visited[i]=1; printf("%c ",g->vex[i].c); p=g->vex[i].first; while( p ) { if(!visited[p->index]) { DFS(g,p->index,visited); } p=p->next; } } void TraDFS(Graph *g) { int i; int visited[MAXVEX]; for(i=0;i<MAXVEX;i++) { visited[i]=0; } for(i=0;i<g->numvex;i++) { if(!visited[i]) { DFS(g,i,visited); } } } //BFS遍历 void TraBFS(Graph *g) { int i,j; LinkQueue q; int visited[MAXVEX]; for(i=0;i<MAXVEX;i++) { visited[i]=0; } InitQueue(&q); for(i=0;i<g->numvex;i++) { if(!visited[i]) { printf("%c ",g->vex[i].c); visited[i]=1; EnQueue(&q, i); while(!QueueEmpty(&q)) { DeQueue(&q,&i); GraphNode *p = g->vex[i].first; while( p ) { if(!visited[p->index]) { printf("%c ",g->vex[p->index].c); visited[p->index]=1; EnQueue(&q,p->index); } p=p->next; } } } } } int main(){ Graph g; create(&g); print(&g); printf("DFS遍历结果: "); TraDFS(&g); printf(" BFS遍历结果为: "); TraBFS(&g); printf(" "); return 0; }
一开始出队列写错了,广度遍历不对,找了好久的原因。