圖的遍歷是指從圖中的某一個頂點出發,按照某種搜索方法沿著圖中的邊對圖中的所有頂點訪問一次且僅訪問一次。注意到樹是一種特殊的圖,所以樹的遍歷實際上也可以看作是一種特殊的圖的遍歷。圖的遍歷主要有兩種算法:廣度優先搜索(Breadth-First-Search)和深度優先搜索(Depth-First-Search)。
深度優先搜索算法所遵循的搜索策略是盡可能“深”地搜索一個圖。它的基本思想就是:首先訪問圖中某一起始頂點v,然后由v出發,訪問與v鄰接且未被訪問的任一頂點w1,再訪問與w1鄰接且未被訪問的任一頂點w2,……重復上述過程。當不能再繼續向下訪問時,依次退回到最近被訪問的頂點,若它還有鄰接頂點未被訪問過,則從該點開始繼續上述搜索過程,直到圖中所有頂點均被訪問過為止。使用遞歸來實現(https://www.zhihu.com/question/20507130)
廣度優先搜索類似于二叉樹的層序遍歷,它的基本思想就是:首先訪問起始頂點v,接著由v出發,依次訪問v的各個未訪問過的鄰接頂點w1,w2,…,wi,然后再依次訪問w1,w2,…,wi的所有未被訪問過的鄰接頂點;再從這些訪問過的頂點出發,再訪問它們所有未被訪問過的鄰接頂點……依次類推,直到圖中所有頂點都被訪問過為止。
廣度優先搜索是一種分層的查找過程,每向前走一步可能訪問一批頂點,不像深度優先搜索那樣有往回退的情況,因此它不是一個遞歸的算法。為了實現逐層的訪問,算法必須借助一個輔助隊列,以記錄正在訪問的頂點的下一層頂點。
DFS : 2 0 1 3
BFS : 2 0 3 1
在圖論中,拓撲排序(Topological Sorting)是一個有向無環圖(DAG, Directed Acyclic Graph)的所有頂點的線性序列。且該序列必須滿足下面兩個條件:
1.每個頂點出現且只出現一次。
2.若存在一條從頂點 A 到頂點 B 的路徑,那么在序列中頂點 A 出現在頂點 B 的前面。
有向無環圖(DAG)才有拓撲排序,非DAG圖沒有拓撲排序一說。
它是一個 DAG 圖,那么如何寫出它的拓撲排序呢?這里說一種比較常用的方法:
1.從 DAG 圖中選擇一個 沒有前驅(即入度為0)的頂點并輸出。
2.從圖中刪除該頂點和所有以它為起點的有向邊。
3.重復 1 和 2 直到當前的 DAG 圖為空或當前圖中不存在無前驅的頂點為止。后一種情況說明有向圖中必然存在環。
可以使用在工期排序、大小關系排列、選課時的先修課(即要先修某某課才能學這一門課,先學了C語言再學數據結構這樣)等情況。
內容來自(http://blog.csdn.net/lisonglisonglisong/article/details/45543451)
#include <iostream>
#include <cstdio>
#include <list>
#include <queue>
using namespace std;
class Graph
{
int V; //結點數目
list<int> *adj; //鄰接矩陣
int* inDegree; //入度數組
queue<int> q; //入度為0的隊列
void BFSUtil(int v, bool visited[]); //內部接口
void DFSUtil(int v, bool visited[]);
public:
Graph(int v);
~Graph();
void addEdge(int v, int w);
bool topoSort();
void DFS(int v); //外部接口
void BFS(int v);
};
Graph::Graph(int v)
{
this->V = v;
adj = new list<int>[v];
inDegree = new int[v];
for(int i = 0; i < v; i++) //新生成的圖每個節點的入度都為0
inDegree[i] = 0;
}
Graph::~Graph()
{
delete [] adj;
delete [] inDegree;
}
void Graph::addEdge(int v, int w) //點v w相連接
{
adj[v].push_back(w);
inDegree[w]++;
}
bool Graph::topoSort()
{
for(int i = 0; i < V; i++)
if(inDegree[i]==0)
q.push(i);
int cnt = 0, v; //cnt統計遍歷節點數目 v記錄此時遍歷節點
while(!q.empty())
{
v = q.front();
q.pop();
printf("%d ",v);
cnt++;
for(list<int>::iterator i=adj[v].begin(); i!=adj[v].end(); i++)
if(!(--inDegree[*i]))
q.push(*i);
}
if(cnt == V)
return true;
else
return false;
}
void Graph::BFSUtil(int v, bool visited[])
{
queue<int> que;
visited[v] = true;
que.push(v);
int node; //出隊元素
while(!que.empty())
{
node = que.front();
printf("%d ",node);
que.pop();
for(list<int>::iterator i = adj[node].begin(); i != adj[node].end(); ++i)
if(!visited[*i])
{
visited[*i] = true;
que.push(*i);
}
}
}
void Graph::BFS(int v)
{
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
BFSUtil(v, visited);
}
void Graph::DFSUtil(int v, bool visited[])
{
visited[v] = true;
printf("%d ",v);
for(list<int>::iterator i = adj[v].begin(); i != adj[v].end(); ++i)
if(!visited[*i])
{
visited[*i] = true;
DFSUtil(*i, visited);
}
}
void Graph::DFS(int v)
{
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
DFSUtil(v, visited);
}
int main()
{
Graph g(4);
g.addEdge(0,1);
g.addEdge(0,2);
g.addEdge(1,2);
g.addEdge(2,0);
g.addEdge(2,3);
g.addEdge(3,3);
// g.topoSort();
g.BFS(2);
printf("\n");
g.DFS(2);
return 0;
}