第6章 图

本文详细介绍了如何使用狄克斯特拉算法解决单源点最短路径问题,并通过实例演示了算法的具体步骤。同时提供了基于邻接链表的C#实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6.4.2 最短路径

2. 狄克斯特拉(Dikastra)算法

对于求单源点的最短路径问题,狄克斯特拉(Dikastra)提出了一个按路径长度递增的顺序逐步产生最短路径的构造算法。狄克斯特拉的算法思想是:设置两个顶点的集合S和T,集合S中存放已找到最短路径的顶点,集合T中存放当前还未找到最短路径的顶点。初始状态时,集合S中只包含源点,设为v0,然后从集合T中选择到源点v0路径长度最短的顶点u加入到集合S中,集合S中每加入一个新的顶点u都要修改源点v0到集合T中剩余顶点的当前最短路径长度值,集合T中各顶点的新的最短路径长度值为原来的当前最短路径长度值与从源点过顶点u到达该顶点的新的最短路径长度中的较小者。此过程不断重复,直到集合T中的顶点全部加到集合S中为止。

以下图为例:

其对源点1运用Dikastra算法得出的结果如下:

 

根据邻接链表存储结构实现Dikastra算法:(邻接链表的实现在前面的博客)

public List<VexListNode<T>> Dikastra(GraphAdjList<T> graph, GraphNode<T> node, out int[] weights)
        {
            List<VexListNode<T>> vexNodes = new List<VexListNode<T>>();
            vexNodes.Add(new VexListNode<T>(node));

            bool[] marker = new bool[graph.NodeNum];
            weights = new int[graph.NodeNum];
            int indexer = graph.IsNode(node);
            marker[indexer] = true;
            weights[indexer] = 0;

            while (vexNodes.Count < graph.NodeNum)
            {
                AdjListNode<T> minAdjNode = null;
                int minWeight = 0;
                VexListNode<T> minInVexNode=null;
                VexListNode<T> minOutVexNode=null;

                VexListNode<T> currentVexNode = null;
                AdjListNode<T> currentAdjNode = null;
                for (int i = 0; i < graph.NodeNum; i++)
                {
                    if (marker[i] == true)
                    {
                        currentVexNode = graph.vexList[i];
                        currentAdjNode = currentVexNode.FirstAdj;

                        while (currentAdjNode != null)
                        {
                            if (marker[currentAdjNode.AdjVexIndex] == false)
                            {
                                if (minAdjNode == null || weights[i] + currentAdjNode.Weight < minWeight)
                                {
                                    minAdjNode = currentAdjNode;
                                    minInVexNode = graph.vexList[currentAdjNode.AdjVexIndex];
                                    minWeight = weights[i] + currentAdjNode.Weight;
                                    minOutVexNode = currentVexNode;
                                }
                            }

                            currentAdjNode = currentAdjNode.Next;
                        }
                    }
                }

                VexListNode<T> vexNode = new VexListNode<T>(minInVexNode.Node);
                vexNode.FirstAdj = new AdjListNode<T>(minAdjNode.Name, graph.IsNode(minOutVexNode.Node), minAdjNode.Weight);
                vexNodes.Add(vexNode);
                marker[minAdjNode.AdjVexIndex] = true;
                weights[minAdjNode.AdjVexIndex] = minWeight;
            }

            return vexNodes;
        }


 

调用代码:

            GraphAdjList<int> adjList = new GraphAdjList<int>(100);

            //Inial graph object
            GraphNode<int> node1 = new GraphNode<int>(1);
            GraphNode<int> node2 = new GraphNode<int>(2);
            GraphNode<int> node3 = new GraphNode<int>(3);
            GraphNode<int> node4 = new GraphNode<int>(4);
            GraphNode<int> node5 = new GraphNode<int>(5);
            GraphNode<int> node6 = new GraphNode<int>(6);
            GraphNode<int> node7 = new GraphNode<int>(7);
            GraphNode<int> node8 = new GraphNode<int>(8);

            adjList.SetNode(node1);
            adjList.SetNode(node2);
            adjList.SetNode(node3);
            adjList.SetNode(node4);
            adjList.SetNode(node5);
            adjList.SetNode(node6);
            adjList.SetNode(node7);
            adjList.SetNode(node8);

            adjList.SetEdge(0, node1, node2, 1);
            adjList.SetEdge(1,node1, node3, 4);
            adjList.SetEdge(2,node1, node5, 6);
            adjList.SetEdge(3, node1, node4, 3);
            adjList.SetEdge(4, node1, node6, 12);
            adjList.SetEdge(5, node2, node4, 4);
            adjList.SetEdge(6, node2, node3, 2);
            adjList.SetEdge(7, node3, node5, 2);
            adjList.SetEdge(8, node4, node2, 1);
            adjList.SetEdge(9, node4, node3, 1);
            adjList.SetEdge(10, node4, node8, 1);
            adjList.SetEdge(11, node4, node7, 8);
            adjList.SetEdge(12, node5, node3, 3);
            adjList.SetEdge(13, node5, node8, 2);
            adjList.SetEdge(14, node6, node4, 1);
            adjList.SetEdge(15, node7, node4, 1);
            adjList.SetEdge(16, node7, node8, 2);
            adjList.SetEdge(17, node7, node6, 2);
            adjList.SetEdge(18, node8, node5, 1);
            adjList.SetEdge(19, node8, node7, 2);

            int[] weights;
            var list = adjList.Dikastra(adjList, node1, out weights);

            int index = adjList.IsNode(node1);
            foreach (var vexNode in list)
            {
                System.Console.Write("Node:");
                System.Console.Write(vexNode.Node.Value);
                System.Console.Write("  TotalWeights:");
                System.Console.Write(weights[adjList.IsNode(vexNode.Node)]);

                if (vexNode.FirstAdj != null)
                {
                    System.Console.Write("  Edage:");
                    System.Console.Write(adjList.vexList[vexNode.FirstAdj.AdjVexIndex].Node.Value);
                    System.Console.Write(" -> (");
                    System.Console.Write(vexNode.FirstAdj.Weight);
                    System.Console.Write(") -> ");
                    System.Console.Write(vexNode.Node.Value);
                }

                System.Console.WriteLine();
            }

            System.Console.ReadKey();

输出结果:

Node:1  TotalWeights:0
Node:2  TotalWeights:1  Edage:1 -> (1) -> 2
Node:4  TotalWeights:3  Edage:1 -> (3) -> 4
Node:3  TotalWeights:3  Edage:2 -> (2) -> 3
Node:8  TotalWeights:4  Edage:4 -> (1) -> 8
Node:5  TotalWeights:5  Edage:3 -> (2) -> 5
Node:7  TotalWeights:6  Edage:8 -> (2) -> 7
Node:6  TotalWeights:8  Edage:7 -> (2) -> 6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值