有向网邻接矩阵求最短路径之Dijsktra迪杰斯特拉算法的理解和C#代码实现

基本概念

设置两个顶点的集合S和T,集合S中存放已找到最短路径的顶点,集合T中存放当前还未找到最短路径的顶点。
初始状态是集合S中只包含源点,设为V0,然后每加入一个新的顶点u都要修改源点v0到集合T中剩余顶点的当前最短路径长度值与集合T中各顶点的新的最短路径长度中的较小者。

算法理解

1.引入两个数组,一个一位数组ShortPathArr,保存源点到各个顶点的最短路径的长度,一个二维数组PathMatrixArr,用来保存从源点到某个顶点的最短路径上的顶点。例如PathMatrix[v][w]=true,意为w是源点到顶点v的最短路径上的顶点。

public void Dijkstra(ref bool[,] pathMatrixArr, ref int[] shortPathArr, Node<T> n){}

2.为了表示某顶点的最短路径是否已经找到,在算法里声明了一个一维数组final,如果final[i]为true,则表示已经找到第i个顶点的最短路径。

bool[] final = new bool[nodes.Length];

3.初始化两个参数数组和final数组,final数组默认各顶点到源点的最短路径为未找到。shortPathArr数组默认为邻接矩阵中,源点到各顶点的权值,pathMatrixArr数组默认为false,设置所有顶点到源点的路径上都有源点和顶点自身。设置源点到自身距离为0,到自身的最短距离为已找到。

//初始化
for(int i = 0; i < nodes.Length; ++i)
{
	final[i] = false;
	shortPathArr[i] = matrix[GetIndex(n), i]; //设置源点到各点的最短路径的长度
	for(int j = 0; j < nodes.Length; j++)
	{
		pathMatrixArr[i, j] = false;//初始化顶点i的路径,路径上没有顶点
	}
	if (shortPathArr[i] != 0 && shortPathArr[i] < int.MaxValue)
	{
		pathMatrixArr[i, GetIndex(n)] = true;//设置顶点i到源点的路径上有源点
		pathMatrixArr[i, i] = true;//设置顶点i到源点的路径上有顶点i
	}
}
//n为源点,其到自身长度为0,其到自身的路径已找到
shortPathArr[GetIndex(n)] = 0;
final[GetIndex(n)] = true;

4.声明最小值变量默认为整型最大值,在没有找到最短路径的顶点里,寻找到源点最近的顶点,其在数组中的下标存入k,更新最小值为该顶点到源点的最短路径,设置顶点k在final数组中为true,即为找到最短路径

int min = int.MaxValue;
for(int j = 0; j < nodes.Length; j++)
{
	//如果源点到j顶点的最短路径还没找到
	if (!final[j])
	{
		if (shortPathArr[j] < min)
		{
			//如果源点到j顶点的路径最小,下标存入k,更新最小值
			k = j;
			min = shortPathArr[j];
		}
	}
}
final[k] = true;//设置源点到顶点k的最小路径已找到

5.在未找到最短路径的顶点中,更新这些顶点到源点的权值,即最短路径,如果新的源点到k加k到其他顶点路径之和比原来的权值小,就更新源点到这些顶点的路径数组的状态,将更新后的源点到k的路径赋值给其他顶点,即更新源点到其他顶点的路径,因为会覆盖其他顶点原本的路径数组,所以需要再次设置源点到其他顶点的路径上有其他顶点自身

for (int j = 0; j < nodes.Length; j++)
{
	if (!final[j] && (min + matrix[k, j] < shortPathArr[j]))
	{
		//如果源点到顶点j的路径未找到,并且源点到顶点k的路径加顶点k到j的路径小于源点到顶点j的路径
		shortPathArr[j] = min + matrix[k, j];//更新源点到j的最短路径
		for(int w = 0; w < nodes.Length; w++)
		{
			pathMatrixArr[j, w] = pathMatrixArr[k, w];
		}
		//更新源点到j的路径上的状态,for循环里将源点到k的路径赋给j,并将路径上的顶点j设为true,得到最新的源点到j的最短路径
		pathMatrixArr[j,j]=true;
	}
}

完整实现

public void Dijkstra(ref bool[,] pathMatrixArr, ref int[] shortPathArr, Node<T> n)
{
    /*pathMatrixArr数组是二维数组,用来保存从源点到某个顶点的最短路径上的顶点。
        例如PathMatrix[v][w]=true,意为w是源点到顶点v的最短路径上的顶点
        shortPathArr数组是一维数组,用来保存源点到各个顶点的最短路径的长度*/
    int k = 0;
    bool[] final = new bool[nodes.Length];
    //初始化
    for(int i = 0; i < nodes.Length; ++i)
    {
        final[i] = false;
        shortPathArr[i] = matrix[GetIndex(n), i]; //设置源点到各点的最短路径的长度
        for(int j = 0; j < nodes.Length; j++)
        {
            pathMatrixArr[i, j] = false;//初始化顶点i的路径,路径上没有顶点
        }
        if (shortPathArr[i] != 0 && shortPathArr[i] < int.MaxValue)
        {
            pathMatrixArr[i, GetIndex(n)] = true;//设置顶点i到源点的路径上有源点
            pathMatrixArr[i, i] = true;//设置顶点i到源点的路径上有顶点i
        }
    }
    //n为源点,其到自身长度为0,其到自身的路径已找到
    shortPathArr[GetIndex(n)] = 0;
    final[GetIndex(n)] = true;

    for(int i = 0; i < nodes.Length; i++)
    {
        int min = int.MaxValue;
        for(int j = 0; j < nodes.Length; j++)
        {
            //如果源点到j顶点的最短路径还没找到
            if (!final[j])
            {
                if (shortPathArr[j] < min)
                {
                    //如果源点到j顶点的路径最小,下标存入k,更新最小值
                    k = j;
                    min = shortPathArr[j];
                }
            }
        }
        final[k] = true;//设置源点到顶点k的最小路径已找到
        for (int j = 0; j < nodes.Length; j++)
        {
            if (!final[j] && (min + matrix[k, j] < shortPathArr[j]))
            {
                //如果源点到顶点j的路径未找到,并且源点到顶点k的路径加顶点k到j的路径小于源点到顶点j的路径
                shortPathArr[j] = min + matrix[k, j];//更新源点到j的最短路径
                for(int w = 0; w < nodes.Length; w++)
                {
                    pathMatrixArr[j, w] = pathMatrixArr[k, w];
                }
                //更新源点到j的路径上的状态,for循环里将源点到k的路径赋给j,并将路径上的顶点j设为true,得到最新的源点到j的最短路径
                pathMatrixArr[j,j]=true;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/u012187817/article/details/82562435