图的实现方法有2种,在之前的一篇博文图的深度遍历中有介绍。在同样的2种图的存储方式的基础上,可以进行图的广度遍历。
图的邻接矩阵法,依然是申请完全连续的空间。通过二维数组空间来存储和访问图中每个边的存在性(或权值)。
int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
edge是一个数组指针。
图的邻接表法,是利用单链式结构(邻接表)存储每个点的可直达节点。并申请连续的空间存储这些邻接表的首结点地址(如果该点没有可直达节点,那首结点位置就为NULL)。
typedef struct edge{
int vertex;
struct edge* next;
}st_edge;
st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
在DFS中,访问的顺序是受到递归逻辑控制的。而BFS中,我们需要借助队列来控制访问的顺序。在另一篇博文中,实现的是线性物理结构的队列。这一次使用链式物理结构来实现队列。我们使用双向链表来存储队列,这样的好处是表头可以快速删除节点,表尾可以快速插入节点。
- typedef struct qElement{
- int value;
- struct qElement* pre;
- struct qElement* next;
- }st_qElement;
- st_qElement* front = NULL;
- st_qElement* rear = NULL;
对队列的操作:
1. 入队:将一个新元素加入队列(插在队尾)
2. 出队:将队尾元素删除
- void putQueue(int vertex)
- {
- st_qElement* qe = (st_qElement*)malloc(sizeof(st_qElement));
- qe->value = vertex;
- qe->next = NULL;
- qe->pre = NULL;
- if(front == NULL || rear == NULL)
- front = rear = qe;
- else{
- rear->next = qe;
- qe->pre = rear;
- rear = qe;
- }
- }
- int* getQueue()
- {
- if(front ==NULL || rear == NULL)
- return NULL;
- else{
- int* res = (int*)malloc(sizeof(int));
- *res = front->value;
- st_qElement* p = front;
- front = front->next;
- if(front == NULL)
- rear = front;
- else
- {
- front->pre = NULL;
- }
- free(p);
- p = NULL;
- return res;
- }
- }
BFS的遍历顺序是按层序。每一层的访问顺序都是由上一层访问的顺序决定好的,这个顺序是存储在队列中。
当访问某一个节点时,就为下一层访问其所有邻接节点做好准备,即将其所有邻接节点依次入队。
那么,整个BFS的访问就是依次从队列中取队头元素,访问它。(当然,首个节点是主动放进队中的。)
邻接矩阵的BFS实现:
- void bfs(int (*edge)[VERTEXNUM], int* vetexStatusArr)
- {
- printf("BFS: ");
- int i;
- for(i=0;i<VERTEXNUM;i++)
- bfscore(edge, i, vetexStatusArr);
- printf("\n");
- }
- void bfscore(int (*edge)[VERTEXNUM], int i, int* vetexStatusArr)
- {
- putQueue(i);
- int* qeValue = NULL;
- while((qeValue = getQueue()) != NULL)
- {
- if(vetexStatusArr[*qeValue] == 0)
- {
- printf("%d ", *qeValue);
- vetexStatusArr[*qeValue] = 1;
- //把与点vertex邻接的点都加进队列
- for(int k=0;k<VERTEXNUM;k++)
- if(edge[*qeValue][k]==1)
- putQueue(k);
- }
- free(qeValue);
- qeValue = NULL;
- }
- }
邻接表的实现BFS实现:
- void bfscore(st_edge** edge, int i, int *vertexStatusArr)
- {
- putQueue(i);
- int *qeValue = NULL;
- while((qeValue = getQueue()) != NULL)
- {
- if(vertexStatusArr[*qeValue] == 0)
- {
- vertexStatusArr[*qeValue] = 1;
- printf("%d ", *qeValue);
- st_edge *p = *(edge + *qeValue);
- while(p != NULL)
- {
- putQueue(p->vertex);
- p = p->next;
- }
- }
- free(qeValue);
- qeValue = NULL;
- }
- }
- void bfs(st_edge** edge, int* vertexStatusArr)
- {
- printf("BFS: ");
- int i;
- for(i=0;i<VERTEXNUM;i++)
- bfscore(edge, i, vertexStatusArr);
- printf("\n");
- }
- #include <stdio.h>
- #include <malloc.h>
- #define VERTEXNUM 5
- //双向链表存储的队列
- typedef struct qElement{
- int value;
- struct qElement* pre;
- struct qElement* next;
- }st_qElement;
- st_qElement* front = NULL;
- st_qElement* rear = NULL;
- void putQueue(int vertex);
- int* getQueue();
- void createGraph(int (*edge)[VERTEXNUM], int start, int end);
- void display(int (*edge)[VERTEXNUM]);
- void bfs(int (*edge)[VERTEXNUM],int i,int* vetexStatusArr);
- void bfscore(int (*edge)[VERTEXNUM], int i, int* vetexStatusArr);
- void putQueue(int vertex)
- {
- st_qElement* qe = (st_qElement*)malloc(sizeof(st_qElement));
- qe->value = vertex;
- qe->next = NULL;
- qe->pre = NULL;
- if(front == NULL || rear == NULL)
- front = rear = qe;
- else{
- rear->next = qe;
- qe->pre = rear;
- rear = qe;
- }
- }
- int* getQueue()
- {
- if(front ==NULL || rear == NULL)
- return NULL;
- else{
- int* res = (int*)malloc(sizeof(int));
- *res = front->value;
- st_qElement* p = front;
- front = front->next;
- if(front == NULL)
- rear = front;
- else
- {
- front->pre = NULL;
- }
- free(p);
- p = NULL;
- return res;
- }
- }
- void createGraph(int (*edge)[VERTEXNUM], int start, int end)
- {
- edge[start][end] = 1;
- }
- void display(int (*edge)[VERTEXNUM])
- {
- int i,j;
- for(i=0;i<VERTEXNUM;i++)
- {
- for(j=0;j<VERTEXNUM;j++)
- printf("%d ", edge[i][j]);
- printf("\n");
- }
- }
- void bfs(int (*edge)[VERTEXNUM], int* vetexStatusArr)
- {
- printf("BFS: ");
- int i;
- for(i=0;i<VERTEXNUM;i++)
- bfscore(edge, i, vetexStatusArr);
- printf("\n");
- }
- void bfscore(int (*edge)[VERTEXNUM], int i, int* vetexStatusArr)
- {
- putQueue(i);
- int* qeValue = NULL;
- while((qeValue = getQueue()) != NULL)
- {
- if(vetexStatusArr[*qeValue] == 0)
- {
- printf("%d ", *qeValue);
- vetexStatusArr[*qeValue] = 1;
- //把与点vertex邻接的点都加进队列
- for(int k=0;k<VERTEXNUM;k++)
- if(edge[*qeValue][k]==1)
- putQueue(k);
- }
- free(qeValue);
- qeValue = NULL;
- }
- }
- int main()
- {
- int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
- int i, j;
- for(i=0;i<VERTEXNUM;i++)
- for(j=0;j<VERTEXNUM;j++)
- edge[i][j] = 0;
- int *vetexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
- for(i=0;i<VERTEXNUM;i++)
- vetexStatusArr[i] = 0;
- createGraph(edge, 0, 3);
- createGraph(edge, 0, 4);
- createGraph(edge, 3, 1);
- createGraph(edge, 3, 2);
- createGraph(edge, 4, 1);
- display(edge);
- bfs(edge, vetexStatusArr);
- free(edge);
- return 1;
- }
邻接表存储方式的BFS完整代码:
- #include <stdio.h>
- #include <malloc.h>
- #define VERTEXNUM 5
- typedef struct edge{
- int vertex;
- struct edge* next;
- }st_edge;
- typedef struct qElement{
- int value;
- struct qElement* pre;
- struct qElement* next;
- }st_qElement;
- st_qElement* front = NULL;
- st_qElement* rear = NULL;
- void putQueue(int vertex)
- {
- st_qElement* qe = (st_qElement*)malloc(sizeof(st_qElement));
- qe->value = vertex;
- qe->next = NULL;
- qe->pre = NULL;
- if(front == NULL || rear == NULL)
- front = rear = qe;
- else
- {
- rear->next = qe;
- qe->pre = rear;
- rear = qe;
- }
- }
- int* getQueue()
- {
- if(front == NULL || rear == NULL)
- return NULL;
- else
- {
- int *res = (int*)malloc(sizeof(int));
- *res = front->value;
- st_qElement* p = front;
- front = front->next;
- if(front == NULL)
- rear = front;
- else
- front->pre = NULL;
- free(p);
- p = NULL;
- return res;
- }
- }
- void display(st_edge** edge)
- {
- int i;
- st_edge* p;
- for(i=0;i<VERTEXNUM;i++)
- {
- printf("%d: ", i);
- p = *(edge+i);
- while(p != NULL)
- {
- printf("%d ", p->vertex);
- p = p->next;
- }
- printf("\n");
- }
- }
- void createGraph(st_edge** edge, int start, int end)
- {
- st_edge* newedge = (st_edge*)malloc(sizeof(st_edge));
- newedge->vertex = end;
- newedge->next = NULL;
- edge = edge + start;
- while(*edge != NULL)
- edge = &((*edge)->next);
- *edge = newedge;
- }
- void bfscore(st_edge** edge, int i, int *vertexStatusArr)
- {
- putQueue(i);
- int *qeValue = NULL;
- while((qeValue = getQueue()) != NULL)
- {
- if(vertexStatusArr[*qeValue] == 0)
- {
- vertexStatusArr[*qeValue] = 1;
- printf("%d ", *qeValue);
- st_edge *p = *(edge + *qeValue);
- while(p != NULL)
- {
- putQueue(p->vertex);
- p = p->next;
- }
- }
- free(qeValue);
- qeValue = NULL;
- }
- }
- void bfs(st_edge** edge, int* vertexStatusArr)
- {
- printf("BFS: ");
- int i;
- for(i=0;i<VERTEXNUM;i++)
- bfscore(edge, i, vertexStatusArr);
- printf("\n");
- }
- int main()
- {
- st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
- int i;
- for(i=0;i<VERTEXNUM;i++)
- edge[i] = NULL;
- int *vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
- for(i=0;i<VERTEXNUM;i++)
- vertexStatusArr[i] = 0;
- createGraph(edge, 0 ,3);
- createGraph(edge, 0, 4);
- createGraph(edge, 3, 1);
- createGraph(edge, 3, 2);
- createGraph(edge, 4, 1);
- display(edge);
- bfs(edge, vertexStatusArr);
- return 1;
- }