本文主要根据floyd算法生成最短路径(包含最短路径值和最短路径经过的所有节点)
首先在数据库中存储创建点表,点的字段包括ID,经度,纬度;线表,线的字段包括IDE(即点的唯一标示值),线的两个端点id1,id2
全局变量//利用哈希表存储相应点,便于根据点ID找到点
Hashtable p = new Hashtable();
//利用哈希表存储相应边,便于根据边ID找到边
Hashtable eg = new Hashtable();
//用来存储最初的点与点之间的权重值
float[,] originweight=new float[19,19];
//该数组中的权重值是经过更新后的权重值
float[,] weight = new float[19,19];
//存储了任意两点之间最终的路径节点
UltrativePath[,] road=new UltrativePath[19,19];
//存储任意两点之间经过过渡点的路径,Path为ArrayList保存了唯一个值,过渡点
Path[,] PathEdge=new Path[19,19];
//从数据库中读取点表中的数据
private void readdb()
{
//打开数据库后,与数据库建立连接
SqlConnection con = new SqlConnection(“server=.;uid=sa;pwd=432101234;database=虚拟校园;”);
try
{
con.Open();
SqlDataAdapter sda = new SqlDataAdapter(“select * from daolujd;”, con);
DataSet ds = new DataSet();
sda.Fill(ds);
DataTable dt=ds.Tables[0];
DataRowCollection drc=dt.Rows;
DataColumnCollection dcc = dt.Columns;
for (int i = 0; i < drc.Count; i++)
{
DataRow dr=drc[i];
Point pp;
//根据读取的数据库中的每一行的数据,取出行中的数据根据点表中的字段,赋给每个点,由p全局变量添加保存
pp.IDP=(int)float.Parse(dr[0].ToString());
pp.name=dr[1].ToString();
pp.longi=float.Parse(dr[2].ToString());
pp.lati=float.Parse(dr[3].ToString());
p.Add(pp.IDP,pp);
}
}
catch (Exception er)
{
MessageBox.Show(er.ToString());
con.Close();
}
}
同理从数据库中读取边表的数据
private void readbb()
{
SqlConnection con = new SqlConnection(“server=.;uid=sa;pwd=432101234;database=虚拟校园;”);
try
{
con.Open();
SqlDataAdapter sda = new SqlDataAdapter(“select * from bianb;”, con);
DataSet ds = new DataSet();
sda.Fill(ds);
DataTable dt = ds.Tables[0];
DataRowCollection drc = dt.Rows;
DataColumnCollection dcc = dt.Columns;
for (int i = 0; i < drc.Count; i++)
{
//索引的使用,方便了相同类型对象的调取
DataRow dr = drc[i];
Edge ege;
ege.IDE =(int)float.Parse(dr[0].ToString());
ege.ID1 =(int)float.Parse(dr[1].ToString());
ege.ID2 =(int)float.Parse(dr[2].ToString());
ege.distance = distance(ege.ID1,ege.ID2);
eg.Add(ege.IDE, ege);
}
}
catch (Exception er)
{
MessageBox.Show(er.ToString());
con.Close();
}
}
//根据点数据算出点之间的距离权重然后将该值赋给全局变量存储相应的点之间的权重值
public void matrixSet()
{
for(int i=1;i<=eg.Count;i++)
{
Edge temp;int tempid1=0,tempid2=0;
temp=(Edge)eg[i];
tempid1 = temp.ID1; tempid2 = temp.ID2;
weight[temp.ID1,temp.ID2]=temp.distance;
weight[temp.ID2,temp.ID1]=temp.distance;
originweight[temp.ID1, temp.ID2] = temp.distance;
originweight[temp.ID2, temp.ID1] = temp.distance;
}
for (int i = 1; i < 19; i++)
{
for (int j = 1; j < 19; j++)
{
float weighttemp=weight[i,j];
float a = 0;
if (weight[i, j] ==a)
{
weight[i, j] = float.MaxValue;
weight[j, i] = float.MaxValue;
}
if (originweight[i, j] == a)
{
originweight[i, j] = float.MaxValue;
originweight[j, i] = float.MaxValue;
}
}
}
//不能按下面的语句写,二者引用的为同一个地址,当weight变化时originweight也随之变化,我们这里需要的是不变。
// originweight=weight;
}
//接下来根据floyd算法给权重矩阵weight,PathEdge赋值
public void Floyd()
{
//这里k点作为插入点
for (int k = 1; k < 19; k++)
{
//m和n作为路径的端点,所有的点对根据已经生成的或者原来的路径距离矩阵进行最短路径的生成
for (int m = 1; m < 19; m++)
{
//如果插入点和起点为同一点就跳出
if (m==k) continue;
//如果插入点和起始点之间不连通跳出
if (weight[m,k] == float.MaxValue) continue;//算法优化
for (int n = 1; n < 19; n++)
{
//如果终点和起始点重合或者终点和插入点重合跳出
if (n == k || m == n) continue;
//如果插入点和终点不连通跳出
if ((weight[k, n] == float.MaxValue)) continue;
if (weight[m, n] > weight[m, k] + weight[k, n])
{
//起始点的距离等于插入点和起始点的距离和
weight[m, n] = weight[m, k] + weight[k, n];
//weight[n, m] = weight[m, n];//程序中任何一句话都应该清楚其含义,或者说其意义都是独一无二的,不能无端多出一句也不能少一句,增之一分则嫌长,短之一分则嫌短
//为两点间的路径创建路径对象
Path p = new Path();
//根据路径对象中的a存储中间的节点,即过渡点,只有一个
p.a.Add(k);
//MessageBox.Show(“起点”+m+”终点”+n+”过渡点”+k);
//存储任意两点间的路径序号列对象
PathEdge[m, n] = p;
}
}
}
}
//MessageBox.Show(“”+PathEdge[11,1].a[0]);
}
//输出最短路径之间的节点,这里通过倒回去查找任意两点之间的最短路径经过的节点
public void Display()
{
Path temp=new Path(); int m = 0, n = 0, k = 0;
//p,q分别代表了起始点和终止点
for (int p = 1; p < 19; p++)
{
for (int q = 1; q < 19; q++)
{
if (p == q) continue;
m = p; n = q; UltrativePath lujing; lujing.ap = new ArrayList(); road[m, n] = lujing;
//n在这里代表终点,针对该起始点之间的包含各经过节点的路径,先添加终止点
//
string zzlujing=””;
//根据事先已经生成的起点过渡点终点路径倒回去查到内部的节点,PathEdge中的对象Path中只有一个元素,即temp中只有一个元素
temp= PathEdge[p, q];int tempk=0;
if (m == 18 && n== 5)
MessageBox.Show(“123”);
if (temp != null)
{
tempk = (int)temp.a[0];
if (originweight[tempk, n] != float.MaxValue)
{
road[m, n].ap.Add(n);
while (temp != null)
{
//这里k代表了两点之间的过渡点
k = (int)temp.a[0];
temp = PathEdge[p, k];
road[m, n].ap.Add(k);
}
road[m, n].ap.Add(m);
}
else
{
road[m, n].ap.Add(m);
while (temp != null)
{
//这里k代表了两点之间的过渡点
k = (int)temp.a[0];
temp = PathEdge[k, q];
road[m, n].ap.Add(k);
}
road[m, n].ap.Add(n);
}
}
//road[n, m] = road[m, n];
for(int z=road[m,n].ap.Count-1;z>=0;z–)
zzlujing=zzlujing+road[m,n].ap[z].ToString()+”-“;
//MessageBox.Show(zzlujing);
write2db(m,n,zzlujing);
}
}
//MessageBox.Show(“” + road[1, 18].ap.Count);
//string zzlujing1 = “”;
//for (int z = road[18, 1].ap.Count – 1; z >= 0; z–)
// zzlujing1 = zzlujing1 + road[18, 1].ap[z].ToString() + “-“;
//MessageBox.Show(“” + road[18,1].ap.Count+”路径”+zzlujing1);
}
//用于存储任意两点之间的路径的中间过渡点,只有一个值
class Path
{
public ArrayList a=new ArrayList();
}
//用于存储从数据库中读取的点数据
public struct Point
{
public int IDP;
public string name;
public float longi;
public float lati;
}
用于存储从数据库中读取的边数据值
struct Edge
{
public int IDE;
public int ID1;
public int ID2;
public float distance;
}
//根据display方法对下面的结构体赋值,该结构体包含了任意两点之间的最短路径节点
struct UltrativePath
{
public ArrayList ap;
}