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;
}