图的遍历之广度优先搜索(Breadth First Search)

来源:互联网 发布:g76螺纹编程实例 编辑:程序博客网 时间:2024/05/22 03:28

描述

广度优先搜索算法(Breadth First Search)与树的层序遍历(level-order traversal)类似,基本思想是思想是:

  1. 从图中某顶点v出发,访问v之后,并将其访问标志置为已被访问,即visited[i]=1;
  2. 依次访问v的各个未曾访问过的邻接点;
  3. 分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到;
  4. 如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。

如果用广度优先搜索算法对下图中结点进行搜索,从结点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
原创粉丝点击