常用的兩種方法:
鄰接表與鄰接矩陣
每一個點對應一個集合set(鄰接表),存儲與此點相連的點。
1.
-)點用連續存儲
a. 鄰接表用連續存儲表
b. 鄰接表用鏈式表
List neighbors[max_size];
二)點與鄰接表都用鏈式表
class Edge{
Vertex *end_point; //邊的終點
Edge *next_edge; //鄰接表的下一條邊
}
class Vertex{
Edge *first_edge; // 鄰接表的第一條邊
Vertex *next_vertex; // 下一個點
class digraph
{
Vertex *first_vertex;
}
2. 固定集合大小max_set, 看成是bit string, 可以用STL中的bitset. 其實質上是下面的鄰接矩陣.
鄰接矩陣:
或者乾脆用二維數組。
bool adjcency[max_size][max_size];
當表示無向圖時有adjcency[v][w]=adjcency[w][v];
表示有向圖時, adjcency[v][w]表示圖中是否有從v到w的邊.
權
以上方式都可以表示邊的權,
例如用鏈式表時,可在Edge加個變量weight。
List的Record包含權值與點的標號。
而鄰接矩陣就用Record代替bool。
圖的遍歷
DFS(深度優先搜索)
遞歸算法
visit(V);
for(each vertex w adjacent to v)
traverse(w);
1,圖可能有迴路的,爲防止死循環,需要設置是否已經訪問標記。
2,圖可能不連通,需要對每一個點都進行DFS。
template <int max_size> // 注意template奇怪用法
void Digraph<max_size>::depth_first(void (*visit)(Vertex &)) const
{
bool visited[max_size];
Vertex v;
for (all v in G) visited[v] = false;
for (all v in G) if (!visited[v])
traverse(v, visited, visit);
}
template <int max_size>
void Digraph<max_size>::traverse(Vertex &v, bool visited[],
void (*visit)(Vertex &)) const
/*
Pre: v is a vertex of the Digraph.
Post: The depth-first traversal, using function *visit, has been completed
for v and for all vertices that can be reached from v.
Uses: traverse recursively.
*/
{
Vertex w;
visited[v] = true;
(*visit)(v);
for (all w adjacent to v)
if (!visited[w])
traverse(w, visited, visit);
}
BFS(廣度優先搜索)
隊列+標記
拓撲排序(有向無迴路圖acyclic)
每個點出現在它的後繼之前。
DFS:
遞歸: 找到沒有後繼的節點放到後面。
O(V+E)
BFS:
維護一個數組,記錄每個點的前繼的數目。先雙重循環初始化其前繼數目,
將前繼數目爲0的插入到拓撲隊列中去
BFS: 當結點前繼數目爲0時, 說明此結點可以插入到拓撲序列中去, 然後一個循環相應的前繼數目減一。
單源最短路徑(權非負)
Dijkstra
貪心: 每次將到當前點集合中未訪問的距離最短的節點加入到當前點集合中
width="728" scrolling="no" height="90" frameborder="0" align="middle" src="http://download1.csdn.net/down3/20070601/01184120111.htm" marginheight="0" marginwidth="0">