重新整理数据结构与算法(c#)——算法套路迪杰斯特拉算法[三十一]

前言

迪杰斯特拉算法 是求最短路径方法的其中一种,这个有什么作用呢?

有一张图:

假设求G点到其他各点的最小路径。

是这样来的。

比如找到了和G点相连接所有点,ABED。这时候确定GA是一定是最短的,为什么这么说呢?G->A和G从别的点到A,一旦G走BED 一定会大于GA,后续就跟不可能大于了。

所以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。

上面说其实有点模糊。

是这样的,如果从G为出发点确认了n个点,那么剩下的m个点怎么确认呢?

肯定就是从G从到先到G最短的点,尝试是否有其他路,如果没有,那么就确认了。

正文

代码如下:

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

结果:

原文地址:https://www.cnblogs.com/aoximin/p/13340068.html