图的广度优化搜索简介
所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。一般的实现里,其邻居节点尚未被检验过的节点会被放置在一个被称为 open 的容器中(例如队列或是链表),而被检验过的节点则被放置在被称为 closed 的容器中。(open-closed表)
与深度优化搜索相比,深度优化搜索并不能找出最短路径。而广度优化搜索正是为了这个目标才出现的。
实现过程
注:以下图片取自:数据结构(七)图
实现关键:
* 需要一个队列
* 不能够使用递进的方法
我的想法是分成三个部分:
1. 插入顶点,将顶点入队列
2. 遍历顶点之后的所有树,进入队列
3. 依次出列,从1开始循环,直到所有顶点被遍历到
代码实现
核心部分:
void bfs(AdjGraphPtr adj, int *marked, int pos, QueuePtr q) {
if (*(marked + pos) == 0) {
//one
insertQueue(q, adj->vertexList[pos]->data);
*(marked + pos) = 1;
//two
EdgePtr e = adj->vertexList[pos]->firstEdge;
int vPos;
while (e == NULL) {
insertQueue(q, e->adjvex);
vPos = _vertexPos(adj, e->adjvex);
*(marked + vPos) = 1;
e = e->next;
}
//three
while (q->head != NULL) {
VTYPE vertex = outQueue(q);
printf("%c\n", vertex);
//vPos = _vertexPos(a, vertex);
//bfs(a, marked, vPos, s); //错误
vPos = _vertexPos(adj, vertex);
e = adj->vertexList[vPos]->firstEdge;
while (e != NULL) {
vPos = _vertexPos(adj, e->adjvex);
if (*(marked + vPos) == 0) {
insertQueue(q, e->adjvex);
*(marked + vPos) = 1;
}
e = e->next;
}
}
}
}
void breadthFirstSearch(AdjGraphPtr adj){
QueuePtr q = createQueue();
int length = adj->vNum;
int *marked = (int *)malloc(sizeof(int)*length);
memset(marked, 0, sizeof(int)*length);
for (int i = 0; i < length; i++) {
if (*(marked + i) == 0)
bfs(adj, marked, i, q); //first:0
}
free(marked);
}
ADT:
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define MAXVEX 100
#define VTYPE char
typedef struct EdgeNode {
VTYPE adjvex;
int weight;
struct EdgeNode *next;
} Edge, *EdgePtr;
typedef struct VertexNode {
VTYPE data;
EdgePtr firstEdge;
} Vertex, *VertexPtr;
typedef struct {
VertexPtr vertexList[MAXVEX];
int vNum;
} AdjGraph, *AdjGraphPtr;
typedef struct qnode {
VTYPE data;
struct qnode *next;
} QueueNode, *QueueNodePtr;
typedef struct {
QueueNodePtr head;
QueueNodePtr tail;
} Queue, *QueuePtr;
QueuePtr createQueue();
QueueNodePtr createQueueNode(VTYPE key);
void insertQueue(QueuePtr q, VTYPE key);
VTYPE outQueue(QueuePtr q);
void deleteQueue(QueuePtr q);
void freeAdj(AdjGraphPtr a);
int _vertexPos(const AdjGraphPtr m, const VTYPE key);
EdgePtr createEdgeNode(VTYPE key);
void insertVertex(AdjGraphPtr adj, const VTYPE key);
void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight);
AdjGraphPtr createAdjGraph(VTYPE *v, int v_length,
int *e, int e_length_1, int e_length_2) ; //test
void bfs(AdjGraphPtr adj, int *marked, int pos, QueuePtr q);
void breadthFirstSearch(AdjGraphPtr adj);
完整代码:
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define MAXVEX 100
#define VTYPE char
typedef struct EdgeNode {
VTYPE adjvex;
int weight;
struct EdgeNode *next;
} Edge, *EdgePtr;
typedef struct VertexNode {
VTYPE data;
EdgePtr firstEdge;
} Vertex, *VertexPtr;
typedef struct {
VertexPtr vertexList[MAXVEX];
int vNum;
} AdjGraph, *AdjGraphPtr;
typedef struct qnode {
VTYPE data;
struct qnode *next;
} QueueNode, *QueueNodePtr;
typedef struct {
QueueNodePtr head;
QueueNodePtr tail;
} Queue, *QueuePtr;
QueuePtr createQueue();
QueueNodePtr createQueueNode(VTYPE key);
void insertQueue(QueuePtr q, VTYPE key);
VTYPE outQueue(QueuePtr q);
void deleteQueue(QueuePtr q);
void freeAdj(AdjGraphPtr a);
int _vertexPos(const AdjGraphPtr m, const VTYPE key);
EdgePtr createEdgeNode(VTYPE key);
void insertVertex(AdjGraphPtr adj, const VTYPE key);
void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight);
AdjGraphPtr createAdjGraph(VTYPE *v, int v_length,
int *e, int e_length_1, int e_length_2) ; //test
void bfs(AdjGraphPtr adj, int *marked, int pos, QueuePtr q) {
if (*(marked + pos) == 0) {
insertQueue(q, adj->vertexList[pos]->data);
*(marked + pos) = 1;
EdgePtr e = adj->vertexList[pos]->firstEdge;
int vPos;
while (e == NULL) {
insertQueue(q, e->adjvex);
vPos = _vertexPos(adj, e->adjvex);
*(marked + vPos) = 1;
e = e->next;
}
while (q->head != NULL) {
VTYPE vertex = outQueue(q);
printf("%c\n", vertex);
//vPos = _vertexPos(a, vertex);
//bfs(a, marked, vPos, s); //错误
vPos = _vertexPos(adj, vertex);
e = adj->vertexList[vPos]->firstEdge;
while (e != NULL) {
vPos = _vertexPos(adj, e->adjvex);
if (*(marked + vPos) == 0) {
insertQueue(q, e->adjvex);
*(marked + vPos) = 1;
}
e = e->next;
}
}
}
}
void breadthFirstSearch(AdjGraphPtr adj){
QueuePtr q = createQueue();
int length = adj->vNum;
int *marked = (int *)malloc(sizeof(int)*length);
memset(marked, 0, sizeof(int)*length);
for (int i = 0; i < length; i++) {
if (*(marked + i) == 0)
bfs(adj, marked, i, q); //first:0
}
free(marked);
}
void main() {
int e[13][3] = {
{ 'A', 'F', 60 },
{ 'A', 'E', 30 },
{ 'A', 'C', 10 },
{ 'F', 'A', 60 },
{ 'F', 'E', 20 },
{ 'E', 'A', 30 },
{ 'E', 'D', 50 },
{ 'D', 'E', 50 },
{ 'D', 'C', 11 },
{ 'C', 'D', 11 },
{ 'C', 'A', 10 },
{ 'C', 'B', 5 },
{ 'B', 'C', 5 }
};
const int e_length_1 = 13;
const int e_length_2 = 3;
VTYPE v[6] = { 'A','F','E','D','C','B' };
const int v_length = 6;
AdjGraphPtr adj = createAdjGraph(v, v_length, e, e_length_1, e_length_2);
breadthFirstSearch(adj);
freeAdj(adj);
}
QueuePtr createQueue() {
QueuePtr q = (QueuePtr)malloc(sizeof(Queue));
memset(q, 0, sizeof(Queue));
q->head = q->tail = NULL;
return q;
}
QueueNodePtr createQueueNode(VTYPE key) {
QueueNodePtr q = (QueueNodePtr)malloc(sizeof(Queue));
memset(q, 0, sizeof(QueueNode));
q->next = NULL;
q->data = key;
return q;
}
void insertQueue(QueuePtr q, VTYPE key) {
QueueNodePtr a = createQueueNode(key);
if (q->head == NULL) { //notice
q->head = q->tail = a;
}
else {
q->tail->next = a;
q->tail = a;
}
}
VTYPE outQueue(QueuePtr q) {
VTYPE v;
if (q->head != NULL) { //notice
v = q->head->data;
QueueNodePtr tmp = q->head->next;
free(q->head);
q->head = tmp;
}
else {
v = NULL;
}
return v;
}
void deleteQueue(QueuePtr q) {
if (q->head != NULL) { //notice
QueueNodePtr tmp = q->head;
QueueNodePtr tmp2;
while (tmp != NULL) {
tmp2 = tmp;
tmp = tmp->next;
free(tmp2);
}
}
free(q);
}
void freeAdj(AdjGraphPtr a) {
for (int i = 0; i < a->vNum; i++) {
EdgePtr tmp = a->vertexList[i]->firstEdge;
while (tmp->next != NULL) {
EdgePtr t = tmp;
tmp = tmp->next;
free(t);
}
free(tmp);
free(a->vertexList[i]);
}
free(a);
}
EdgePtr createEdgeNode(VTYPE key) {
EdgePtr a = (EdgePtr)malloc(sizeof(Edge));
memset(a, 0, sizeof(Edge));
a->adjvex = key;
a->next = NULL;
return a;
}
int _vertexPos(const AdjGraphPtr m, const VTYPE key) {
for (int i = 0; i < m->vNum; i++) {
if (m->vertexList[i]->data == key)
return i;
}
return -1;
}
void insertVertex(AdjGraphPtr adj, const VTYPE key) {
for (int i = 0; i < adj->vNum; i++) {
if (adj->vertexList[i] == key)
return;
}
VertexPtr vNode = (VertexPtr)malloc(sizeof(Vertex));
memset(vNode, 0, sizeof(Vertex));
vNode->data = key;
vNode->firstEdge = NULL;
adj->vertexList[adj->vNum] = vNode;
adj->vNum++;
}
void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight) {
int pos_a = _vertexPos(adj, a);
EdgePtr avex = createEdgeNode(b);
avex->weight = weight;
if (adj->vertexList[pos_a]->firstEdge == NULL) {
adj->vertexList[pos_a]->firstEdge = avex;
}
else {
EdgePtr tmp = adj->vertexList[pos_a]->firstEdge;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = avex;
}
}
AdjGraphPtr createAdjGraph(VTYPE *v, int v_length, int *e, int e_length_1, int e_length_2) {
AdjGraphPtr adj = (AdjGraphPtr)malloc(sizeof(AdjGraph));
memset(adj, 0, sizeof(AdjGraph));
for (int i = 0; i < v_length; i++) {
insertVertex(adj, v[i]);
}
EdgePtr tmp = NULL;
for (int i = 0; i < e_length_1; i++) {
VTYPE a = *(e + e_length_2 * i + 0);
VTYPE b = *(e + e_length_2 * i + 1);
int weight = *(e + e_length_2 * i + 2);
insertEdge(adj, a, b, weight);
}
return adj;
}