算法实现参照博客https://blog.csdn.net/xv740234390/article/details/45152735,对此表示感谢!本文在此算法基础上根据自己论文,改进而来,特此说明。本文所用工具为:VS2017 .NetFrameWork4.6.1平台单线程+Access数据库。
数据库构建情况如下图所示:
论文路网情况如下图所示:
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");
}
}
}