图的遍历之广度优先搜索(Breadth First Search)
来源:互联网 发布:g76螺纹编程实例 编辑:程序博客网 时间:2024/05/22 03:28
描述
广度优先搜索算法(Breadth First Search)与树的层序遍历(level-order traversal)类似,基本思想是思想是:
- 从图中某顶点v出发,访问v之后,并将其访问标志置为已被访问,即visited[i]=1;
- 依次访问v的各个未曾访问过的邻接点;
- 分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到;
- 如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。
如果用广度优先搜索算法对下图中结点进行搜索,从结点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 doubletypedef 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);}
0 0
- 图的遍历之广度优先搜索(Breadth First Search)
- 算法:图的广度优先遍历(Breadth First Search)
- 图的广度优先搜索(Breadth First Search)
- 广度优先搜索(Breadth first search)
- 图搜索算法之广度优先搜索(Breadth First Search,BFS)
- 广度优先搜索算法(Breadth-First-Search,BFS)
- 广度优先搜索算法(Breadth-First-Search)
- 广度优先搜索算法(breadth First Search, BFS)
- 广度优先搜索(Breadth First Search,BFS)
- [数据结构]广度优先搜索算法(Breadth-First-Search,BFS)
- 关于广度优先遍历(Breadth First Search)的提纲性内容
- LeetCode上Tag为广度优先搜索BFS(Breadth-first Search)的题目整理
- BFS—— Breadth First Search 广度优先算法
- BFS——广度优先算法(Breadth First Search)
- 图的遍历 之 广度优先搜索
- 图的遍历之广度优先搜索
- 广度优先遍历(Breadth-FirstTraversal)
- 一道题弄懂宽度优先搜索 Breadth first search
- 整数化成字符串
- JAVA 线程
- 统计学中及计算机视觉中的各种 距离 汇总。。。
- IOS 代码书写风格规范
- 黑马程序员_集合Collection
- 图的遍历之广度优先搜索(Breadth First Search)
- Upstart笔记(by quqi99)
- 曲线拟合
- Python3.4读写Excel
- 阿里巴巴研发工程师 笔试题最后大题(数据库查询)
- 用java写一个小型的聊天窗口 新手学java
- JSP Servlet学习笔记——使用fileupload上传文件
- JavaWeb 用Intellij IDEA创建基于tomcat和jetty的Servlet
- 关于 hot code replace fail 问题