1 圖的表示
2. 有向圖的遍歷算法:深度優先
3. 有向圖的遍歷算法:廣度優先
4 代碼反思
5. 下載
1. 圖的表示
1.1 圖的定義
圖G定義爲V和E的集合G={V, E},其中V表示圖中的所有的頂點集合,E表示的是G中的所有的邊的集合。圖按照E中的元素是否有方向,分爲有向圖和無向圖。
1.2 圖的表示方法
上面給出的數學上圖的定義,那麼在計算機中如何表示圖?通常意義上,有下面的兩種方法:鄰接表和鄰接矩陣表示法。
無向圖的鄰接表和鄰接矩陣表示如下所示:
有向圖的鄰接表和鄰接矩陣表示如下所示:
根據上面的表示方法,下面定義圖G的這種數據結構(鄰接表),首先定義圖的頂點GraphVertex:
// 頂點顯示的符號
public char Symbol { get; set; }
// 頂點當前顏色
public VertexColor Color { get; set; }
// 頂點和開始節點之間的距離
public int Distance { get; set; }
// 廣度遍歷父節點
public GraphVertex Parent { get; set; }
// 深度優先搜索中的開始時間
public int StartTime { get; set; }
// 深度優先搜索中的結束時間
public int FinishTime { get; set; }
// 頂點對應的邊
public List<GraphEdge> FollowEdges { get; set; }
定義圖G的邊的數據結構:
// 邊開始頂點,在鄰接表的存儲中其實沒有必要存儲
public GraphVertex From { get; set; }
// 結束頂點
public GraphVertex To { get; set; }
// 邊權重
public int Weight { get; set; }
定義圖:
// 數據成員,這裏假設的是頂點的symbol是各個不相同的
private Hashtable graph =
new Hashtable();
private int time = 0;
整體上的結構如下:
2. 有向圖的深度優先算法
2.1 基本算法
其中d表明的是某個節點第一次被發現的時間點,f表明從節點出發的全部節點已經被發現的時間。
2.2 設計實現
// 深度優先遍歷算法
public void DepthFirstVisit(GraphVertex v)
{
// 剛剛被發現,顏色爲gray
Console.WriteLine(v.Symbol);
v.Color = VertexColor.GRAY;
this.time++;
// 開始時間
v.StartTime = this.time;
foreach (GraphEdge edge in v.FollowEdges)
{
// 還未被發現
if (edge.To.Color == VertexColor.WHITE)
{
edge.To.Parent = v;
DepthFirstVisit(edge.To);
}
}
// 如果邊都已經發現完成
v.Color = VertexColor.BLACK;
this.time++;
v.FinishTime = this.time;
}
public void DepthFirstTravel()
{
// 全局時間變量
this.time = 0;
// 初始化
GraphVertex v;
foreach (DictionaryEntry e in this.graph)
{
v = (GraphVertex)e.Value;
v.Color = VertexColor.WHITE;
v.Parent = null;
}
// 遞歸調用
// 隊所有的頂點
foreach (DictionaryEntry e in this.graph)
{
v = (GraphVertex)e.Value;
// 頂點爲白色
if (v.Color == VertexColor.WHITE)
{
DepthFirstVisit(v);
}
}
}
3. 有向圖的遍歷算法:廣度優先
3.1 基本算法
其中color域表示的是當前某個節點被發現的狀態。如果是white表明沒有被發現,gray表示當前頂點已經被發現,但是從該節點出發的節點還沒有被全部發現。parent域定義的是在搜索算法時父節點。distance域表明的是從節點s到某個發現的節點v的路徑距離。
3.2 設計實現
// 廣度優先遍歷算法,同時生成廣度優先樹
public void BreadthFirstTravel(GraphVertex s)
{
// 初始化所有節點
GraphVertex v;
foreach (DictionaryEntry e in this.graph)
{
v = (GraphVertex)e.Value;
v.Color = VertexColor.WHITE;
v.Distance = int.MaxValue;
v.Parent = null;
}
// 發現第一個節點
s.Color = VertexColor.GRAY;
s.Distance = 0;
s.Parent = null;
// 初始化隊列
Queue context =
new Queue();
context.Enqueue(s);
// 如果隊列不空的話
while (context.Count != 0)
{
// 隊首元素出隊
v = context.Dequeue() as GraphVertex;
Console.WriteLine(v.Symbol);
// 遍歷v的節點
foreach (GraphEdge item in v.FollowEdges)
{
if ( item.To.Color == VertexColor.WHITE)
{
item.To.Color = VertexColor.GRAY;
item.To.Distance = v.Distance + 1;
item.To.Parent = v;
context.Enqueue(item.To);
}
}
v.Color = VertexColor.BLACK;
}
}
4. 代碼反思
上面的搜索代碼結構是比較典型的搜索結構:首先定義隊列或者是棧來保存程序運行狀態,如果容器不空,取出元素,然後對取出的元素做一些處理。
5. 代碼下載
/Files/xuqiang/DirectedGraph1.rar