广度优先搜索算法(Breadth First Search)与树的层序遍历(level-order traversal)类似,基本思想是思想是:
如果用广度优先搜索算法对下图中结点进行搜索,从结点a出发,先搜索处理 它的子结点b和c,即深度为2的结点;然后搜索深度为3的子结点d、e、f、g;最后搜索深度为4的 结点h。
伪代码如下:
bool visited[MAX_VERTEXT_NUM]; // 访问标记数组
void BFS_Traversal(Graph G, int v)
{
visit(v); // 访问初始顶点
visited[v] = true; // v已访问
Enqueue(Q, v); // 顶点v入队列
while(!isEmpty(Q))
{
Dequeue(Q, v); // 顶点v出队列
for(w=FirstNeighbor(G,v); w>=0; w=NextNeighbor(G,v))
if(!visited[w]) // 检测v的所有邻接点
{
visit(w); // 若w未访问,访问之
visited[w]=true; // 标记
Enqueue(Q, w); // 顶点w入队列
}
}
}
void BFS(Graph G) // 设访问函数为visit()
{
for(i=0; i<G.vexnum; ++i)
visited[i] = false; // 初始化
for(i=0; i<G.vexnum; ++i) // 从0号顶点开始遍历
if(!visited[i]) // 对每个连通分量调用一次BFS
BFS_Traversal(G,i); // Vi未访问过,从Vi开始BFS
}
(图的存储是邻接表的深度优先搜索)
#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#define Max_Vertex_Num 100 //最大顶点数
typedef char VertexType; //顶点数类型定义
typedef int EdgeType; //边类型定义
typedef struct EdgeNode
{
int adjvex; // 该边所指的顶点的位置
EdgeType weight; //该边的权值
struct EdgeNode *NextEdge; //指向下一条边的指针
}EdgeNode;
typedef struct VertexNode
{
VertexType data; // 顶点信息
EdgeNode *firstEdge; //指向第一条依附该顶点的边表头指针
}VertexNode, AdjList[Max_Vertex_Num];
typedef struct
{
AdjList adjList;
int EdgeNum; // 图的当前边数
int VertexNum; //图的当前顶点数
bool visited[Max_Vertex_Num]; //顶点是否被访问过
}ALGraph;
/* 队列是一种先进先出线性表,队列是线性表的特化 也具有线性表的性质分为:顺序队列与链式队列 链式队列与线性表的单链表相似只不过链式队列只 允许从头部进行删除、尾部进行插入.需要为链式队列 创建一个头结点包括两个指针,指向队头的指针(front) 与指向队尾的指针(rear).当两个指针相等时队列为空*/
typedef struct QueenNode
{
int data; //队列的数据
struct QueenNode *Qnext; //指向下一个结点
}QueenNode,*pQuee;
typedef struct
{
pQuee front; //指向队头的指针
pQuee rear; //指向队尾的指针
}LinkQueen;
void InitQueen(LinkQueen &Queen)
{
Queen.front = Queen.rear = (pQuee)malloc(sizeof(QueenNode));//初始化队头与队尾的指针指向头结点
if(!Queen.front) //生成头结点失败
exit(1);
Queen.front->Qnext = NULL;
}
void DestroyQueen(LinkQueen &Queen)
{
while(Queen.front)
{
Queen.rear = Queen.front->Qnext;
free(Queen.front);
Queen.front = Queen.rear;
}
}
bool IsEmpty(LinkQueen &Queen) //判断队列是否为空
{
if(Queen.front == Queen.rear)
return true;
return false;
}
// 插入元素e为队列Q的新的队尾元素。
void EnQueen(LinkQueen &Queen, int data)
{
pQuee ptr;
ptr = (pQuee)malloc(sizeof(QueenNode)); //动态生成新结点
if(!ptr)
exit(1);
ptr->data = data;
ptr->Qnext = NULL; //队列只能从队尾插入所以下一个结点初始化为NULL
Queen.rear->Qnext = ptr; // 原队尾结点的指针指向新结点,如果新结点为第一个结点则q->rear->next相当于q->front->next
Queen.rear = ptr; // 尾指针指向新结点
}
//删除Q的队头元素,用e返回其值
void DeQueen(LinkQueen &Queen, int *data)
{
pQuee ptr;
if(Queen.front == Queen.rear) // 队列空
exit(1);
ptr = Queen.front->Qnext ; // p指向队头结点
*data = ptr->data; // 将队头元素的值赋给data
Queen.front->Qnext = ptr->Qnext; // 头结点指向下一个结点
if(Queen.rear==ptr) // 删除的是队尾结点
Queen.rear=Queen.front; // 修改队尾指针指向头结点(空队列)
free(ptr); // 释放队头结点
}
// 返回顶点v的位置
int LocateVertex(ALGraph *G, VertexType v)
{
int i = 0;
for(i = 0; v != G->adjList[i].data && i < G->VertexNum; i ++);
if(i >= G->VertexNum)
return -1;
return i;
}
//增加节点
void AddVertex(ALGraph *G)
{
cout << "input vertex number" << endl;
cin >> G->VertexNum;
cout << "input vertex value" << endl;
for(int i = 0; i < G->VertexNum; i++)
{
cin >> G->adjList[i].data;
G->adjList[i].firstEdge = NULL;
}
}
//增加边表
void AddEdge(ALGraph *G)
{
cout << "input edge number" << endl;
cin >> G->EdgeNum ;
VertexType V1, V2;
cout << "input two vertex" << endl;
for(int k = 0; k < G->EdgeNum; k ++)
{
cin >> V1 >> V2;
int i = LocateVertex(G,V1);
int j = LocateVertex(G,V2);
EdgeNode *pe1 = (EdgeNode *)malloc(sizeof(EdgeNode));
pe1->adjvex = i;
pe1->NextEdge = G->adjList[j].firstEdge;
G->adjList[j].firstEdge = pe1;
EdgeNode *pe2 = (EdgeNode *)malloc(sizeof(EdgeNode));
pe2->adjvex = j;
pe2->NextEdge = G->adjList[i].firstEdge;
G->adjList[i].firstEdge = pe2;
}
}
void CreatALGraph(ALGraph *G)
{
AddVertex(G);
AddEdge(G);
}
void PrintALGrap(ALGraph *G)
{
EdgeNode *pe;
cout << "编号 顶点 邻点编号" << endl;
for(int i = 0; i < G->VertexNum; i ++)
{
cout << " " << i << " " << G->adjList[i].data << " ";
for(pe = G->adjList[i].firstEdge; pe; pe = pe->NextEdge)
cout << pe->adjvex << " ";
cout << endl;
}
}
// 广度搜索
void BFS(ALGraph *G, int i)
{
EdgeNode *pe;
LinkQueen queen;
InitQueen(queen);
G->visited[i] = true;
EnQueen(queen,i);
cout << G->adjList[i].data << " "; //打印顶点
while(!IsEmpty(queen))
{
DeQueen(queen,&i);
pe = G->adjList[i].firstEdge;
while(pe)
{
if(!G->visited[pe->adjvex])
{
G->visited[pe->adjvex] = true;
cout << G->adjList[pe->adjvex].data << " "; //打印顶点
EnQueen(queen,pe->adjvex);
}
pe = pe->NextEdge;
}
}
}
void BFS_Traverse(ALGraph *G)
{
int i = 0;
for(i = 0; i < G->VertexNum; i ++)
G->visited[i] = 0;
for(i = 0; i < G->VertexNum; i ++)
if(!G->visited[i])
BFS(G,i);
}
int main()
{
ALGraph GL;
CreatALGraph(&GL);
PrintALGrap(&GL);
BFS_Traverse(&GL);
}
(图的存储是邻接矩阵的深度优先搜索)
#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
const int VERTEX_NUM = 20; // 顶点的最大数
typedef int graph_weight_t; // 边的权值类型 可以为 int float double
typedef struct SArc
{
graph_weight_t Weight; // 权值
}AdjMatrix[VERTEX_NUM][VERTEX_NUM]; // 邻接矩阵
typedef struct SGraph
{
int iVertexNum; // 顶点数
int iArcNum; // 边数
int aVertex[VERTEX_NUM]; // 顶点向量
AdjMatrix mArcs; //邻接矩阵
bool visited[VERTEX_NUM];
}Graph;
/* 队列是一种先进先出线性表,队列是线性表的特化 也具有线性表的性质分为:顺序队列与链式队列 链式队列与线性表的单链表相似只不过链式队列只 允许从头部进行删除、尾部进行插入.需要为链式队列 创建一个头结点包括两个指针,指向队头的指针(front) 与指向队尾的指针(rear).当两个指针相等时队列为空*/
typedef struct QueenNode
{
int data; //队列的数据
struct QueenNode *Qnext; //指向下一个结点
}QueenNode,*pQuee;
typedef struct
{
pQuee front; //指向队头的指针
pQuee rear; //指向队尾的指针
}LinkQueen;
void InitQueen(LinkQueen &Queen)
{
Queen.front = Queen.rear = (pQuee)malloc(sizeof(QueenNode));//初始化队头与队尾的指针指向头结点
if(!Queen.front) //生成头结点失败
exit(1);
Queen.front->Qnext = NULL;
}
void DestroyQueen(LinkQueen &Queen)
{
while(Queen.front)
{
Queen.rear = Queen.front->Qnext;
free(Queen.front);
Queen.front = Queen.rear;
}
}
bool IsEmpty(LinkQueen &Queen) //判断队列是否为空
{
if(Queen.front == Queen.rear)
return true;
return false;
}
// 插入元素e为队列Q的新的队尾元素。
void EnQueen(LinkQueen &Queen, int data)
{
pQuee ptr;
ptr = (pQuee)malloc(sizeof(QueenNode)); //动态生成新结点
if(!ptr)
exit(1);
ptr->data = data;
ptr->Qnext = NULL; //队列只能从队尾插入所以下一个结点初始化为NULL
Queen.rear->Qnext = ptr; // 原队尾结点的指针指向新结点,如果新结点为第一个结点则q->rear->next相当于q->front->next
Queen.rear = ptr; // 尾指针指向新结点
}
//删除Q的队头元素,用e返回其值
void DeQueen(LinkQueen &Queen, int *data)
{
pQuee ptr;
if(Queen.front == Queen.rear) // 队列空
exit(1);
ptr = Queen.front->Qnext ; // p指向队头结点
*data = ptr->data; // 将队头元素的值赋给data
Queen.front->Qnext = ptr->Qnext; // 头结点指向下一个结点
if(Queen.rear==ptr) // 删除的是队尾结点
Queen.rear=Queen.front; // 修改队尾指针指向头结点(空队列)
free(ptr); // 释放队头结点
}
void IintGraph(Graph &graph)
{
//graph = (pGraph)malloc(sizeof(Graph));
graph.iVertexNum = 0;
graph.iArcNum = 0;
for(int i = 0; i < VERTEX_NUM; i++)
graph.aVertex[i] = 0;
for(int i = 0; i < VERTEX_NUM; i ++)
for(int j= 0; j < VERTEX_NUM; j ++)
graph.mArcs[i][j].Weight = 0;
}
void Add_Vertex(Graph &graph)
{
cout << "Add Vertex" << endl;
cout << "Input vertex number:";
cin >> graph.iVertexNum;
cout << "Input vertex value:";
for(int i = 0; i < graph.iVertexNum; i ++)
cin >> graph.aVertex[i];
}
int Locat_vertex(Graph &graph, int vertex)
{
for(int i = 0; i < graph.iVertexNum; i ++)
{
if(graph.aVertex[i] == vertex)
return i;
}
return -1;
}
void Add_Arcs(Graph &graph)
{
cout << "Add Arcs" << endl;
cout << "input arcs numbers:";
cin >> graph.iArcNum;
int iFirst = 0;
int iSecond = 0;
int iRow = 0;
int iCol = 0;
graph_weight_t iWeight = 0;
for(int i = 0; i < graph.iArcNum; i ++)
{
cout << "Input two Arc and Weight(ex. 1 2 32)" << endl;
cin >> iFirst >> iSecond >> iWeight;
iRow = Locat_vertex(graph, iFirst);
iCol = Locat_vertex(graph, iSecond);
graph.mArcs[iRow][iCol].Weight = iWeight;
graph.mArcs[iCol][iRow].Weight = iWeight;
}
}
void Creat_Graph(Graph &graph)
{
cout << "Creat Graph" << endl;
Add_Vertex(graph);
Add_Arcs(graph);
}
void Show_Graph(Graph &graph)
{
cout << "show the graph represented by adjmatrix "<<endl;
for(int row = 0; row < graph.iVertexNum; row ++)
{
for(int col =0; col < graph.iVertexNum; col ++)
{
cout << graph.mArcs[row][col].Weight << "\t";
}
cout << endl;
}
}
void BFS(Graph &graph, int i)
{
LinkQueen queen;
InitQueen(queen);
graph.visited[i] = true;
cout << graph.aVertex[i] << " ";
EnQueen(queen,i);
while(!IsEmpty(queen))
{
DeQueen(queen,&i);
for(int j = 0; j < graph.iVertexNum; j ++)
{
if(graph.mArcs[i][j].Weight==1&&!graph.visited[j])
{
graph.visited[j] = true;
cout << graph.aVertex[j] << " ";
EnQueen(queen,j);
}
}
}
}
void BFS_traversal(Graph &graph)
{
for(int i = 0; i < graph.iVertexNum; i ++)
graph.visited[i] = 0;
for(int j = 0; j < graph.iVertexNum; j ++)
{
if(!graph.visited[j])
BFS(graph,j);
}
}
int main()
{
Graph graph;
IintGraph(graph);
Creat_Graph(graph);
Show_Graph(graph);
BFS_traversal(graph);
}