• 图的遍历BFS广度优先搜索


    图的遍历BFS广度优先搜索

    1. 简介

    BFS(Breadth First Search,广度优先搜索,又名宽度优先搜索),与深度优先算法在一个结点“死磕到底“的思维不同,广度优先算法关注的重点在于每一层的结点进行的下一层的访问。

    2. BFS算法介绍

    BFS算法和核心思路就是:从某个点一直把其邻接点走完,然后任选一个邻接点把与之邻接的未被遍历的点走完,如此反复走完所有结点。类似于树的层序遍历。

    BFS的核心就是要把当前在哪作为一个状态存储,并将这个状态交给队列进行入队操作,故而,

    算法步骤(用队列实现)

    a) 访问指定起始点。

    b) 访问当前顶点的邻接顶点有未被访问的顶点,并将之放入队列中。

    c) 删除队列的队首节点。访问当前队列的队首,前面的步骤。直到队列为空。

    d) 若若途中还有顶点未被访问,则再选一个点作为起始顶点。重复前面的步骤。(针对非连通图)。

    3. 案例图示

    4. 相关代码

    BFS的模板代码如下:

    /**
     * 返回合适的检索数据
     */
    int BFS(Node root, Node target) 
    {
        Queue<Node> queue;  //创建队列
        int step = 0;       // 当前队列的步骤点
        // initialize
        add root to queue;
        // BFS
        while (queue is not empty) 
        {
            step = step + 1;
            //步数逐渐增加
            int size = queue.size();
            for (int i = 0; i < size; ++i) 
            {
                Node cur = the first node in queue;
                if cur is target
                    return step - 1;
                for (Node next : the neighbors of cur) 
                {//这里常用一个二维方向数组实现
                    add next to queue;
                }
                remove the first node from queue;
            }
        }
        return -1;          //出错返回值
    }

    完整代码:

    #include<iostream>
    using namespace std;
    #define matrix_size 20
    typedef struct {
        int weight;
    }AdjMatrix[matrix_size][matrix_size];
    
    struct  Queue{
        int data;
        Queue* next;
    };
    
    
    struct MGraph{
        int vex[matrix_size];
        AdjMatrix arcs;
        int vexnum,arcnum;
    };
    bool visited[matrix_size];    
    
    int LocateVex(MGraph *G ,int v){
        int i;
        for ( i = 0; i < G->vexnum; i++)
        {
            if (G->vex[i]==v)
            {
                break;
            }
        }
        if (i>G->vexnum)
        {
            cout<<"not such vertex"<<endl;
            return -1;
        }
        return i;
    }
    //构造无向图
    void CreateDN(MGraph *G){
        cin>>G->vexnum>>G->arcnum;
        for (int i = 0; i < G->vexnum; i++)
        {
            cin>>G->vex[i];
        }
        for (int i=0; i<G->vexnum; i++) {
            for (int j=0; j<G->vexnum; j++) {
                G->arcs[i][j].weight=0;
            }
        }
        for (int i = 0; i < G->arcnum; i++)
        {
            int v1,v2;
            cin>>v1>>v2;
            int n=LocateVex(G,v1);
            int m=LocateVex(G,v2);
            if (m==-1||n==-1)
            {
                cout<<"not this vertex"<<endl;
                return ;
            }
            G->arcs[n][m].weight=1;
            G->arcs[m][n].weight=1;
        }
        
        return ;
    }
    //输出函数
    void PrintGrapth(MGraph G)
    {
        for (int i = 0; i < G.vexnum; i++)
        {
            for (int j = 0; j < G.vexnum; j++)
            {
                cout<<G.arcs[i][j].weight<<" ";
            }
            cout<<endl;
        }
    }
    void visitVex(MGraph G,int v){
        cout<<G.vex[v]<<" ";
    }
    int FirstAdjVex(MGraph G,int v){
        for (int i = 0; i < G.vexnum; i++)
        {
            //查找与数组下标为v的顶点之间有边的顶点,返回它在数组中的下标
            if (G.arcs[v][i].weight)
            {
                return i;
            }
        }
        return -1;
    }
    int NextAdjVex(MGraph G,int v,int w)
    {
        //从前一个访问位置w的下一个位置开始,查找之间有边的顶点
        for(int i = w+1; i<G.vexnum; i++){
            if(G.arcs[v][i].weight){
                return i;
            }
        }
        return -1;
    }
    
    Queue* InitQueue(){
            Queue* Q=new Queue;
            Q->next=NULL;
            return Q;
    }
    
    //顶点元素v进队列
    void EnQueue(Queue * Q,int v){
        Queue *element = new Queue;
        element->data=v;
        element->next=NULL;
        Queue* temp=Q;
        while (temp->next!=NULL)
        {
            temp=temp->next;
        }
        temp->next=element;
        // cout<<"in enqueue "<<element->data<<" ";
    }
    
    //队头元素出队列
    Queue * DeQueue(Queue *Q,int *u){
        (*u)=Q->next->data;
        Q=Q->next;
        return Q;
    }
    
    //判断队列是否为空
    bool QueueEmpty(Queue *Q){
        if (Q->next==NULL)
        {
            return true;
        }
        return false;
    }
    
    
    //广度优先搜索
    void BFSTraverse(MGraph G){
        int v;
        for ( v = 0; v < G.vexnum; v++)
        {
            visited[v]=false;
        }
        Queue * Q;
        Q=InitQueue();
        for (v=0 ; v <G.vexnum ; v++)
        {
            if (!visited[v])
            {
                visited[v]=true;
                visitVex(G,v);
                EnQueue(Q,G.vex[v]);
                while (!QueueEmpty(Q))
                {
                    int u;
                    Q=DeQueue(Q,&u);
                    u = LocateVex(&G,u);
                    for (int w=FirstAdjVex(G, u); w>=0; w=NextAdjVex(G, u, w)) {
                        if (!visited[w]) {
                            visited[w]=true;
                            visitVex(G, w);
                            EnQueue(Q, G.vex[w]);
                        }
                    }
    
                }
                
            }
        }
    
    }
    
    int main() {
        MGraph G;//建立一个图的变量
        CreateDN(&G);//初始化图
        BFSTraverse(G);//广度优先搜索图
        return 0;
    }

     

    结果:

    8 9
    1 2 3 4 5 6 7 8
    1 2
    2 4
    2 5
    4 8
    5 8
    1 3
    3 6
    6 7
    7 3
    1 2 3 4 5 6 7 8

     

    因上求缘,果上努力~~~~ 作者:每天卷学习,转载请注明原文链接:https://www.cnblogs.com/BlairGrowing/p/13644714.html

  • 相关阅读:
    直线的中点Bresenham算法的实现
    使用git 将自己的本地文件git到github上面的完整过程
    利用Microsoft VC++6.0 的MFC 的绘图工具实现简单图形的绘制
    github常见操作和常见错误及其解决办法
    浅谈软件配置管理工具(github & SVN)
    为Github 托管项目的访问添加SSH keys
    jQuery:用 lightTreeview 实现树形分类菜单的功能 展开收缩分类代码
    程序设计7大面向对象设计原则
    计算机组成原理实验之模拟整机实验考核试题
    计算机组成原理实验之CPU组成与指令周期实验
  • 原文地址:https://www.cnblogs.com/BlairGrowing/p/13644714.html
Copyright © 2020-2023  润新知