從新整理數據結構與算法(c#)——算法套路迪傑斯特拉算法[三十一]

前言

迪傑斯特拉算法 是求最短路徑方法的其中一種,這個有什麼做用呢?算法

有一張圖:數組

假設求G點到其餘各點的最小路徑。測試

是這樣來的。this

好比找到了和G點相鏈接全部點,ABED。這時候肯定GA是必定是最短的,爲何這麼說呢?G->A和G從別的點到A,一旦G走BED 必定會大於GA,後續就跟不可能大於了。code

因此GA爲最短,這時候就肯定了A。這時候開始從A點開始,找到和A點相連可是沒有肯定最短的點,有B、C。G->A->B 大於G->B。而後A能夠到C,這時候肯定G->C 是9。對象

而後從G到各點已經相連中,找到沒有確認的最小路徑,這個就是確認了G->B最短。爲何可以確認呢?由於G到A而後到B大於G->B,那麼能夠確認G到B最短,這是由於GA是最短的,從最短的到不了,其餘的必定大於G->B。blog

上面說其實有點模糊。get

是這樣的,若是從G爲出發點確認了n個點,那麼剩下的m個點怎麼確認呢?string

確定就是從G從到先到G最短的點,嘗試是否有其餘路,若是沒有,那麼就確認了。it

正文

代碼以下:

class Program
{
	private static int INF = int.MaxValue;

	static void Main(string[] args)
	{
		char[] vertex = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
		int N = 65535;// 表示不能夠鏈接
		int[,] matrix = { { N, 5, 7, N, N, N, 2 },
		{ 5, N, N, 9, N, N, 3 },
		{ 7, N, N, N, 8, N, N },
		{ N, 9, N, N, N, 4, N },
		{ N, N, 8, N, N, 5, 4 },
		{ N, N, N, 4, 5, N, 6 },
		{ 2, 3, N, N, 4, 6, N }
		};
		//建立 Graph對象
		Graph graph = new Graph(vertex, matrix);
		//測試, 看看圖的鄰接矩陣是否ok
		graph.showGraph();
		//測試迪傑斯特拉算法
		graph.dsj(2);//C
		graph.showDijkstra();
		Console.Read();
	}
}
class Graph
{
	private char[] vertex;//頂點數組
	private int[,] matrix;//鄰接矩陣
	private VisitedVertex vv;//頂點狀態
	public Graph(char[] vertex, int[,] matrix)
	{
		this.vertex = vertex;
		this.matrix = matrix;
	}

	public void showDijkstra()
	{
		vv.show();
	}

	public void showGraph()
	{
		for (int i = 0; i < vertex.Length; i++)
		{
			for (int j = 0; j < vertex.Length; j++)
			{
				Console.Write(matrix[i, j] + "  ");
			}
			Console.WriteLine();
		}
	}

	public void dsj(int index)
	{
		vv = new VisitedVertex(vertex.Length, index);
		update(index);
		for (int i = 1; i < vertex.Length; i++)
		{
			index = vv.updateArr();
			update(index);
		}
	}

	private void update(int index)
	{
		int len = 0;
		for (int j = 0; j < vertex.Length; j++)
		{
			len = vv.getDis(index) + matrix[index, j];
			if (!vv.isVisited(j) && len < vv.getDis(j))
			{
				vv.updatePre(j, index);
				vv.updateDis(j, len);
			}
		}
	}
}
class VisitedVertex
{

	//記錄各個頂點的訪問狀態
	public int[] already_arr;
	//每一個頂點對應前一個頂點的下標
	public int[] pre_visited;
	//記錄出發點到其餘頂點的距離
	public int[] dis;

	public VisitedVertex(int length, int index)
	{
		already_arr = new int[length];
		pre_visited = new int[length];
		dis = new int[length];
		Array.Fill(dis, int.MaxValue);
		this.already_arr[index] = 1;
		this.dis[index] = 0;
	}

	public int updateArr()
	{
		int min = int.MaxValue, index = 0;
		for (int i = 0; i < already_arr.Length; i++)
		{
			if (already_arr[i] == 0 && dis[i] < min)
			{
				min = dis[i];
				index = i;
			}
		}
		//更新 index 頂點被訪問過
		already_arr[index] = 1;
		return index;
	}
	/// <summary>
	/// 是否訪問過
	/// </summary>
	/// <param name="index">下標距離</param>
	/// <returns></returns>
	public Boolean isVisited(int index)
	{
		return already_arr[index] == 1;
	}
	//更新距離
	public void updateDis(int index, int length)
	{
		dis[index] = length;
	}

	//更新前驅節點
	public void updatePre(int index, int pre)
	{
		pre_visited[index] = pre;
	}
	//返回到某個節點的距離
	public int getDis(int index)
	{
		return dis[index];
	}
	//顯示最後的結果
	//即將三個數組的狀況輸出
	public void show()
	{
		Console.WriteLine("輸出前驅");
		//輸出pre_visited
		foreach (int i in pre_visited)
		{
			Console.Write(i + " ");
		}
		Console.WriteLine();
		char[] vertex = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
		int count = 0;
		foreach (int i in dis)
		{
			if (i != 65535)
			{
				Console.Write(vertex[count] + "(" + i + ") ");
			}
			else
			{
				Console.Write("N ");
			}
			count++;
		}
		Console.WriteLine();
	}
}

結果:

相關文章
相關標籤/搜索