C++ 廣度優先搜索(鄰接表+隊列實現)

C++ 廣度優先搜索(鄰接表+隊列實現)

廣度優先搜索的結果是圖的生成樹,也就是極小連通圖(n個頂點,n-1條邊)

廣度優先搜索 相當於 樹結構的層次遍歷,因此我們可以套用樹的層次遍歷,利用隊列去解決圖的廣度優先搜索

廣度優先搜索步驟:
1.確定一個開始頂點,並且將其標記爲已訪問
2.依次遍歷開始頂點中未被訪問的鄰接頂點,並且標記爲已訪問
3.當某一個開始頂點的鄰接頂點均被訪問完,則以其的一個鄰接頂點作爲開始頂點,重複以上操作。
4.當所有頂點均已被訪問(沒有新的頂點作爲開始頂點)時,搜索結束,程序結束。

假設我們有以下的圖

那麼廣度遍歷的結果應該是:
v1->v2->v3->v4->v5->v6->v7->v8

代碼實現

1.鄰接表實現

#pragma once
#include<iostream>
#include<vector>

using namespace std;

//鄰接表+DFS實現圖的深度優先搜索(無向圖)
struct AdjacenyList
{
    int adjacenyNode;
    AdjacenyList *nextarc;
};

//鄰接表表頭
struct headerList
{
    int headerNode;
    AdjacenyList *firstarc;
};

//鄰接表
class graphAdjacencyList
{
public:
    graphAdjacencyList(int nodeNum)
    {
        this->nodeNum=nodeNum;
        this->hvexArray=new headerList[nodeNum]();
        if(hvexArray==NULL)
        {
            cout<<"out of space"<<endl;
            exit(1);
        }
        for(int i=0;i<nodeNum;++i)
        {
            hvexArray[i].firstarc=NULL;
            hvexArray[i].headerNode=-1;
        }
    }
    ~graphAdjacencyList()
    {
        if(hvexArray!=NULL)
        {
            delete[] hvexArray;
        }
        if(!adjvector.empty())
        {
            for(vector<AdjacenyList*>::iterator it=adjvector.begin();it!=adjvector.end();++it)
            {
                delete (*it);
            }
        }
    }
    void addEdge(int tail,int head)//(tail,head)
    {
        AdjacenyList *adjvex=new AdjacenyList();
        adjvex->nextarc=NULL;
        adjvex->adjacenyNode=head;//鄰接頂點信息
        if((hvexArray+tail)->headerNode==-1)
        {
            //設置頭列表
            (hvexArray+tail)->headerNode=tail;
            (hvexArray+tail)->firstarc=adjvex;
        }
        else
        {
            //設置鄰接表
            AdjacenyList *tempAdjList=(hvexArray+tail)->firstarc;
            while(tempAdjList->nextarc!=NULL)//迭代找到最後一個列表接上
            {
                tempAdjList=tempAdjList->nextarc;
            }
            tempAdjList->nextarc=adjvex;
        }
        adjvector.push_back(adjvex);
    }

    headerList *getList()
    {
        return hvexArray;
    }

private:
    //AdjacenyList *adjvex;
    vector<AdjacenyList*> adjvector;//用vector來管理領接頂點的內存
    headerList *hvexArray;
    int nodeNum;
};

2.廣度優先搜索(BFS)實現

void bfs(graphAdjacencyList &graph,int start,int nodeNum)
{
    vector<bool> visited(nodeNum,false);
    queue<int> q;
    cout<<start;
    q.push(start);
    visited[start]=true;
    while(!q.empty())
    {
        int currentNode = q.front();//取隊頭元素
        AdjacenyList *temp=graph.getList()[currentNode].firstarc;//取當前頂點的第一個鄰接點
        while(temp!=NULL)
        {
            if(visited[temp->adjacenyNode]==false)//未被訪問
            {
                //輸出節點
                cout<<"-->"<<temp->adjacenyNode;
                //更改訪問:已訪問
                visited[temp->adjacenyNode]=true;
                //進隊列
                q.push(temp->adjacenyNode);
                //不需要break
            }
            //已訪問,尋找下一個鄰接點
            temp=temp->nextarc;
        }
        q.pop();
    }
    cout<<endl;
}

實現上圖的廣度搜索

int main(int argc, const char** argv) {
    graphAdjacencyList graph_adjlist(8);
    graph_adjlist.addEdge(0,1);
    graph_adjlist.addEdge(0,2);
    graph_adjlist.addEdge(1,0);
    graph_adjlist.addEdge(1,3);
    graph_adjlist.addEdge(1,4);
    graph_adjlist.addEdge(2,0);
    graph_adjlist.addEdge(2,5);
    graph_adjlist.addEdge(2,6);
    graph_adjlist.addEdge(3,1);
    graph_adjlist.addEdge(3,7);
    graph_adjlist.addEdge(4,1);
    graph_adjlist.addEdge(4,7);
    graph_adjlist.addEdge(5,2);
    graph_adjlist.addEdge(5,6);
    graph_adjlist.addEdge(6,2);
    graph_adjlist.addEdge(6,5);
    graph_adjlist.addEdge(7,3);
    graph_adjlist.addEdge(7,4);

//    printgraphAdjList(graph_adjlist,8);
//    dfs(graph_adjlist,0,8);
    bfs(graph_adjlist,0,8);

    system("pause");
    return 0;
}

結果顯示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章