C#最短路Dijkstra算法与根据拓扑排序的label-correcting算法

这里写自定义目录标题

基本原理

Dij算法和拓扑拍讯的基本原理很多这里不多说,dij算法核心思想就是理解T集合与P集合的含义,并且在程序执行时候记录每个节点的前级节点,可以求解一个点到其他所有点的最短路径。

##数据结构
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

##代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

public class CNode
{
    public int ID;
    public int Name;
    public List<int> OutLink = new List<int>();//出节点的路段
    public List<int> InLink = new List<int>();//进入节点的路段
    public List<int> preNode = new List<int>();//前驱节点
    public int Indegree;//入度
    public int Torder;//拓扑序号
}
public class CLink
{
    public int ID;
    public int InNodeID;
    public int OutNodeID;
    public double Length;
}
public class CNetwork
{
    public List<CNode> m_Node = new List<CNode>();
    public List<CLink> m_Link = new List<CLink>();
    public List<int> m_TopologicalOrder = new List<int>();//拓扑序
    public List<int> P_list = new List<int>();//p标集合
    public int[,] LinkNode;
    public double[] LinkLength;
    public double[] MinCost;
    public int[] pre_list;//前节点集合


    public void InitializationforDJ()
    {
        CLink pLink;
        CNode pNode;
        for (int node = 0; node < m_Node.Count; node++)
        {
            pNode = new CNode();
            m_Node[node].OutLink.Clear();
        }
        LinkNode = new int[m_Link.Count, 2];
        LinkLength = new double[m_Link.Count];
        for (int link = 0; link < m_Link.Count; link++)
        {
            pLink = new CLink();
            pLink = m_Link[link];
            pNode = m_Node[pLink.InNodeID];
            pNode.OutLink.Add(link);
            LinkNode[link, 0] = pLink.InNodeID;
            LinkNode[link, 1] = pLink.OutNodeID;
            LinkLength[link] = pLink.Length;
        }
        MinCost = new double[m_Node.Count];
    }
    public void InitializationforLC()
    {
        CLink pLink;
        CNode pNode1;
        CNode pNode2;
        for (int node = 0; node < m_Node.Count; node++)
        {
            m_Node[node].InLink.Clear();
            m_Node[node].OutLink.Clear();
        }
        LinkNode = new int[m_Link.Count, 2];
        LinkLength = new double[m_Link.Count];
        for (int link = 0; link < m_Link.Count; link++)
        {
            pNode1 = new CNode();
            pNode2 = new CNode();
            pLink = new CLink();
            pLink = m_Link[link];
            pNode1 = m_Node[pLink.InNodeID];
            pNode2 = m_Node[pLink.OutNodeID];
            pNode1.OutLink.Add(link);
            pNode2.InLink.Add(link);
            LinkNode[link, 0] = pLink.InNodeID;
            LinkNode[link, 1] = pLink.OutNodeID;
            LinkLength[link] = pLink.Length;
        }
        MinCost = new double[m_Node.Count];
        for (int i = 0; i < m_Node.Count; i++)
        {
            CNode pNode = new CNode();
            pNode = m_Node[i];
            pNode.Indegree = pNode.InLink.Count;
        }
    }
    public void Dijkstra(int OriginID)
    {
        
        pre_list = new int[m_Node.Count];//前节点集合
        bool[] bContained = new bool[m_Node.Count];
        int node = 0, link = 0;
        int renode = 0, index = 0;
        for (node = 0; node < m_Node.Count; node++)
        {
            MinCost[node] = double.MaxValue;
            pre_list[node] = -1;
            bContained[node] = false;
        }
        P_list.Add(OriginID);
        MinCost[OriginID] = 0;
        int step= OriginID; 
        MinCost[OriginID] = 0;
        bContained[OriginID] = true;
        CNode pNode;
        int pstep = 0;
        StreamWriter sr = File.CreateText("DJoutput.txt");
        StringBuilder sb = new StringBuilder();
        while(P_list.Count<m_Node.Count)
        {
            pNode = new CNode();
            pNode = m_Node[step];
            for (node = 0; node < pNode.OutLink.Count; node++)
            {
                link = pNode.OutLink[node];
                index = LinkNode[link, 1];//outnode
                //T
                if (MinCost[index] > MinCost[pNode.ID] + LinkLength[link])
                {
                    MinCost[index] = MinCost[pNode.ID] + LinkLength[link];
                    pre_list[index] = pNode.ID;
                }
            }
            //找到T标中最小的变为P标号
            double minLength = double.MaxValue;
            for (renode = 0; renode < m_Node.Count; renode++)
            {
                if ((MinCost[renode] < minLength) && (!bContained[renode]))
                {
                    minLength = MinCost[renode];
                    pstep = step;
                    step = renode;
                }
            }
            bContained[step] = true;
            P_list.Add(renode);
    }
    public void TopologicalOrder(int OriginID)//拓扑排序
    {
        int node = 0, link = 0;
        CNode pNode;
        CLink pLink;
        List<int> zeroIndegree = new List<int>();
        int count = 0;
        int index = 1;
        m_TopologicalOrder.Clear();
        while (count < m_Node.Count)//获得各个节点拓扑序号
        {
            for (node = 0; node < m_Node.Count; node++)
            {
                pNode = new CNode();
                pNode = (CNode)m_Node[node];
                if (pNode.Indegree == 0)
                {
                    zeroIndegree.Add(pNode.ID);
                }
                else continue;
            }
            //int copyzeroIndegreeCount = zeroIndegree.Count;
            while (zeroIndegree.Count > 0)
            {
                CNode pNode1 = new CNode();
                pNode1 = (CNode)m_Node[zeroIndegree[0]];
                pNode1.Torder = index;
                zeroIndegree.Remove(zeroIndegree[0]);
                m_TopologicalOrder.Add(pNode1.ID);
                UpdateIndegree(pNode1);
                index++;
                count++;
            }
        }
        //根据起点更新拓扑排序集合
        if (m_TopologicalOrder[0] != OriginID)
        {
            for (node = 0; node < m_Node.Count; node++)
            {
                if (m_TopologicalOrder[node] == OriginID)
                {
                    //int copy = m_TopologicalOrder[node];
                    m_TopologicalOrder[node] = m_TopologicalOrder[0];
                    m_TopologicalOrder[0] = OriginID;
                }
            }
        }
    }
    public void UpdateIndegree(CNode pNode)//更新入度
    {
        pNode.Indegree = 1000;
        int node = 0;
        for (node = 0; node < pNode.OutLink.Count; node++)
        {
            CLink pLink = new CLink();
            pLink = m_Link[pNode.OutLink[node]];
            m_Node[pLink.OutNodeID].Indegree--;
        }
    }
    public void LabelCorrecting(int OriginID)
    {
        int node = 0, link = 0;
        pre_list = new int[m_Node.Count];
        for (node = 0; node < m_Node.Count; node++)
        {
            MinCost[node] = double.MaxValue;
            pre_list[node] = -1;
        }
        CNode pNode;
        MinCost[OriginID] = 0;
        for (int i = 0; i < m_TopologicalOrder.Count; i++)
        {
            pNode=new CNode();
            pNode = m_Node[m_TopologicalOrder[i]];
            for (node = 0; node < pNode.OutLink.Count; node++)
            {
                link = pNode.OutLink[node];
                int index = LinkNode[link, 1];//outnode
                //T
                if (MinCost[index] > MinCost[pNode.ID] + LinkLength[link])
                {
                    MinCost[index] = MinCost[pNode.ID] + LinkLength[link];
                    m_Node[index].OutLink.Add(pNode.ID);
                    pre_list[pNode.ID] = index;
                }
            }
        }
    }
}


 2. 窗体程序
(2)	Form.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace DJandLB
{
    public partial class Form1 : Form
    {
        CNetwork pNetwork;
        public Form1()
        {
            InitializeComponent();
        }

        void LoaddataforDJ()
        {
            pNetwork = new CNetwork();
            String datapath;
            datapath = Directory.GetCurrentDirectory();
            datapath += "\\DJNode.dat";
            pNetwork.ReadNode(datapath);
            datapath = Directory.GetCurrentDirectory();
            datapath += "\\DJLink.dat";
            pNetwork.ReadLink(datapath);
        }
        void LoaddataforLC()
        {
            pNetwork = new CNetwork();
            String datapath;
            datapath = Directory.GetCurrentDirectory();
            datapath += "\\LCNode.dat";
            pNetwork.ReadNode(datapath);
            datapath = Directory.GetCurrentDirectory();
            datapath += "\\LCLink.dat";
            pNetwork.ReadLink(datapath);
        }
        private void btn_Dijkstra_Click(object sender, EventArgs e)
        {
            LoaddataforDJ();
            pNetwork.InitializationforDJ();
            pNetwork.Dijkstra(0);
            //pNetwork.SaveShortestPathforDJ("DJoutput.txt");
            MessageBox.Show("ok!");
        }
        private void btn_LC_Click(object sender, EventArgs e)
        {
            int OriginID = 2;
            LoaddataforLC();
            pNetwork.InitializationforLC();
            pNetwork.TopologicalOrder(OriginID);
            pNetwork.LabelCorrecting(OriginID);
            pNetwork.SaveShortestPathforLC(OriginID,"LCoutput.txt");
            MessageBox.Show("ok!");
        }
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值