基于图论的Dijkstra算法C#窗体应用程序实现

1.前言

算法实现参照博客https://blog.csdn.net/xv740234390/article/details/45152735,对此表示感谢!本文在此算法基础上根据自己论文,改进而来,特此说明。本文所用工具为:VS2017 .NetFrameWork4.6.1平台单线程+Access数据库。
数据库构建情况如下图所示:
基于图论的Dijkstra算法C#窗体应用程序实现_第1张图片
论文路网情况如下图所示:
基于图论的Dijkstra算法C#窗体应用程序实现_第2张图片

2.代码展示

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ShortestPath
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            /*
             *
             *凡有注释“论文中参数--可舍去”的字段,均可删去,注意的是若删去某一字段,需得删除在其他地方的调用!!!
             * 
             */
            connection();
            readstation();
            //以下步骤,可删除,但删除之后DataGridView中无数据源,需结合数据库Database1自行修改
            DataTable dt = new DataTable();
            BindingSource mbs = new BindingSource();
            dt.Columns.Add("NodeID", typeof(int));
            dt.Columns.Add("CurrentNode", typeof(string));
            dt.Columns.Add("NextNode", typeof(string));
            dt.Columns.Add("Distance", typeof(string));
            string _station = "";
            string _distance = "";
            for (int i = 0; i < tu.Count; i++)
            {
                _station = "";
                _distance = "";
                for (int j = 0; j < tu[i].next_station.Count; j++)
                {
                    _station += tu[i].next_station[j].ToString() + "  ";
                }
                for (int j = 0; j < tu[i].distance_list.Count; j++)
                {
                    _distance += tu[i].distance_list[j].ToString() + "  ";
                }
                dt.Rows.Add(tu[i].station_id, tu[i].station_name, _station, _distance);
            }
            mbs.DataSource = dt;
            grd.DataSource = mbs;
        }
        double belta = 0.001;//论文中参数--可舍去
        double lamda = 2;//论文中参数--可舍去
        double[][] alpha;//论文中参数--可舍去
        double vex = 85;//论文中参数--可舍去
        double[] kesi = new double[] { 1, 0.8, 0.3 };//论文中参数--可舍去
        private OleDbConnection dbconn; //数据库连接
        private static List<station> tu = new List<station>();//站点链表
        /// 
        /// 创建节点类
        /// 
        public class station
        {
            public int station_id = 0;
            public string station_name = null;
            public List<int> next_station = new List<int>();
            public List<double> distance_list = new List<double>();
            public double P = 0.0;
            public double T = 10000;
            public int f = -1;
            public station(int id, string name, List<int> next, List<double> dis)
            {
                this.station_id = id;
                this.station_name = name;
                this.next_station = next.ToList();
                this.distance_list = dis.ToList();
            }
            public station()
            {

            }
        }
        /// 
        /// T节点类
        /// 
        public class T
        {
            public int Distance_id;
            public double value;
            public T(int ID, double _value)
            {
                Distance_id = ID;
                value = _value;
            }
            public T()
            {

            }
        }
        /// 
        /// 比较器构造函数
        /// 
        public class Icp : IComparer<T>
        {
            public int Compare(T x, T y)
            {
                return x.value.CompareTo(y.value);
            }
        }
        /// 
        /// 连接Access数据库
        /// 
        void connection()
        {
            dbconn = new OleDbConnection("provider=Microsoft.ACE.OLEDB.12.0;Data Source=Database1.accdb;");
            dbconn.Open();
            if (dbconn.State == ConnectionState.Open)//判断数据库是否连接上
            {
                MessageBox.Show("已建立Access数据库连接!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("未建立Access数据库连接!", "失败", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        /// 
        /// 读取数据库中的元素到tu list中
        /// 
        private void readstation()
        {

            List<int> next_station = new List<int>();
            List<double> next_dis = new List<double>();
            string next_stationstring = "";
            string[] next_stationspilt = new string[10];
            string next_disstring = "";
            string[] next_disspilt = new string[10];
            string strSql = "select Distance.ID,Distance.name,Distance.next_station,Distance.dis from Distance";
            OleDbCommand sc1 = new OleDbCommand();
            sc1.CommandText = strSql;
            sc1.Connection = dbconn;
            OleDbDataReader sda = sc1.ExecuteReader();
            while (sda.Read())
            {
                next_stationstring = sda.GetString(2);
                next_stationspilt = next_stationstring.Split(',');
                for (int i = 0; i < next_stationspilt.Length; i++)
                {
                    next_station.Add(Convert.ToInt32(next_stationspilt[i]));
                }
                next_disstring = sda.GetString(3);
                next_disspilt = next_disstring.Split(',');//分割字符串
                for (int i = 0; i < next_disspilt.Length; i++)
                {
                    next_dis.Add(Convert.ToDouble(next_disspilt[i]));
                }
                station aa = new station(sda.GetInt32(0), sda.GetString(1), next_station, next_dis);
                tu.Add(aa);
                next_station.Clear();
                next_dis.Clear();
            }
        }
        /// 
        /// 改变P标号获取最短路径并给制定的点制定最优前节点
        /// 
        /// 起始点
        /// 终到点
        /// 
        private List<station> get_shortroute(int o, int d) ///改变P标号获取最短路径并给制定的点制定最优前节点
        {
            List<T> Top = new List<T>();
            // List

Pp = new List

(); List<station> S = new List<station>(); T tt = new T(); int k = o; station aa = new station(); tu.ElementAt(o).P = 0; S.Add(tu.ElementAt(o)); while (S.Count < tu.Count) { for (int i = 0; i < tu.ElementAt(k).next_station.Count; i++) { int j = 0; j = tu.ElementAt(k).next_station.ElementAt(i) - 1;//取出下一个车站的ID if (tu.ElementAt(k).distance_list.ElementAt(i) == 0) { return S; } if (tu.ElementAt(j).T > tu.ElementAt(k).P + tu.ElementAt(k).distance_list.ElementAt(i)) { for (int l = 0; l < Top.Count; l++) { if (Top.ElementAt(l).Distance_id == tu.ElementAt(j).station_id) { Top.RemoveAt(l); } } tu.ElementAt(j).T = tu.ElementAt(k).P + tu.ElementAt(k).distance_list.ElementAt(i); tu.ElementAt(j).f = k; Top.Add(new T((tu.ElementAt(j).station_id), tt.value = tu.ElementAt(j).T)); } } Top.Sort(new Icp());//对Top中的元素进行排序 tu.ElementAt(Top.ElementAt(0).Distance_id - 1).P = Top.ElementAt(0).value; S.Add(tu.ElementAt(Top.ElementAt(0).Distance_id - 1)); k = Top.ElementAt(0).Distance_id - 1; Top.RemoveAt(0); } return S; } ///

/// 逆向推导路径 ///
/// /// /// private List<int> get_route(int o, int d) { List<int> route = new List<int>(); int k = d; route.Add(tu.ElementAt(k).station_id); while (tu.ElementAt(k).f != -1 && tu.ElementAt(k).station_id != o)//判断给出的点之间是否连通 { route.Add(tu.ElementAt(k).f + 1); k = tu.ElementAt(k).f; } route.Reverse(); return route; } private void button1_Click(object sender, EventArgs e) { tu.Clear(); textBox3.Text = ""; textBox4.Text = ""; textBox5.Text = ""; readstation(); double dis = 0; List<int> route = new List<int>(); get_shortroute(Convert.ToInt32(textBox1.Text) - 1, Convert.ToInt32(textBox2.Text)); route = get_route(Convert.ToInt32(textBox1.Text), Convert.ToInt32(textBox2.Text) - 1); if (route.Count == 1) { textBox3.Text = "没有连通请重新输入"; MessageBox.Show("没有连通请重新输入"); return; } textBox3.Text = ""; textBox3.Text = route.ElementAt(0).ToString(); for (int i = 1; i < route.Count; i++) { textBox3.Text += ">>"; textBox3.Text += route.ElementAt(i).ToString(); } textBox3.Text = textBox3.Text; for (int i = 0; i < route.Count - 1; i++) { for (int k = 0; k < tu[route[i] - 1].next_station.Count; k++) { if (tu[route[i + 1] - 1].station_id == tu[route[i] - 1].next_station[k]) { dis += tu[route[i] - 1].distance_list[k]; } } } textBox4.Text = dis.ToString(); alpha = new double[tu.Count][]; for (int i = 0; i < 12; i++) { alpha[i] = new double[tu[i].next_station.Count]; for (int j = 0; j < tu[i].next_station.Count; j++) { alpha[i][j] = 0.001; } } for (int i = 12; i < 18; i++) { alpha[i] = new double[tu[i].next_station.Count]; for (int j = 0; j < tu[i].next_station.Count; j++) { alpha[i][j] = 0.002; } } for (int i = 18; i < tu.Count; i++) { alpha[i] = new double[tu[i].next_station.Count]; for (int j = 0; j < tu[i].next_station.Count; j++) { alpha[i][j] = 0.003; } } double dexp = 0; for (int i = 0; i < tu.Count; i++) { for (int j = 0; j < tu[i].distance_list.Count; j++) { dexp = Math.Exp(lamda * (alpha[i][j] * belta)); if (checkBox1.Checked == true) { if (tu[i].next_station[j] == 20) tu[i].distance_list[j] = tu[i].distance_list[j] * 1.0 * dexp / (vex * kesi[1]); else if (tu[i].station_id == 20) tu[i].distance_list[j] = tu[i].distance_list[j] * 1.0 * dexp / (vex * kesi[2]); else tu[i].distance_list[j] = tu[i].distance_list[j] * 1.0 * dexp / (vex * kesi[0]); } else tu[i].distance_list[j] = tu[i].distance_list[j] * 1.0 * dexp / vex; } } dis = 0; for (int i = 0; i < route.Count - 1; i++) { for (int k = 0; k < tu[route[i] - 1].next_station.Count; k++) { if (tu[route[i + 1] - 1].station_id == tu[route[i] - 1].next_station[k]) { dis += tu[route[i] - 1].distance_list[k]; } } } textBox5.Text = dis.ToString("0.000"); } } }

3.运行结果

基于图论的Dijkstra算法C#窗体应用程序实现_第3张图片
基于图论的Dijkstra算法C#窗体应用程序实现_第4张图片

你可能感兴趣的:(C#算法与数据结构)