代码改变世界

(原创)Dijkstra算法

2013-03-26 20:34  Keiven_LY  阅读(215)  评论(0编辑  收藏  举报
说明:该设计可以任意输入起点和终点
 

一、界面设计

    三个listbox,分别为:listbox1,listbox2,listbox3
                        ListBox1存放起点到终点的最短路径值
                        ListBox2存放起点到各个顶点最短路径上,各个顶点的上一节点
                        ListBox3存放起点到终点最短路径上经过的点
    两个Label,分别为Label1,Label2,各自的text为起点和终点
    两个TextBox,分别为txt1,txt2,分别用于输入起点和终点
    两个Button,分别为Button1,Button2,分别为开始和结束按钮
 
二、代码如下:
 
Public Class Form1
 
    '定义二维数组w为节点的带权邻接矩阵,并初始化
    Dim Inf As Double = Double.PositiveInfinity '表示正无穷大
    Dim w(,) = {{0, Inf, Inf, 1.2, 9.2, Inf, 0.5}, {Inf, 0, Inf, 5, Inf, 3.1, 2}, {Inf, Inf, 0, Inf, Inf, 4, 1.5}, {1.2, 5, Inf, 0, 6.7, Inf, Inf}, {9.2, Inf, Inf, 6.7, 0, 15.6, Inf}, {Inf, 3.1, 4, Inf, 15.6, 0, Inf}, {0.5, 2, 1.5, Inf, Inf, Inf, 0}}
   
    Private k As Integer     '用于构造顶点集合数组V()、存放顶点路径l()、存放各顶点的上一顶点t()的循环变量
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
        '**************************初始化*******************************************
        Dim startpoint As Integer  '起点
        Dim endpoint As Integer    '终点
 
        startpoint = Convert.ToInt32(txt1.Text)
        endpoint = Convert.ToInt32(txt2.Text)
 
        Dim num As Integer
        num = w.GetLength(0)   '这里num=7
 
        Dim V(num - 1) As Integer    '用于存放顶点的集合
        For Me.k = 0 To num - 1
            V(k) = k
        Next
        '以上循环是给数组V()赋初值,即所有顶点的集合
 
        Dim l(num - 1) As Double   '数组l()用于存放各顶点到起点的最短距离
        For Me.k = 0 To num - 1
            l(k) = w(startpoint - 1, k)
        Next
        '上面的循环目的是给数组l()赋初值,即起点到其他个点的初始距离(这里定义源节点为最后一个节点,故初始距离为邻接矩阵的最后一行)
 
 
        Dim t(num - 1) As Integer  '数组t()用于存放各顶点的上一节点
        For Me.k = 0 To num - 1
            t(k) = startpoint - 1
        Next
        '上面的循环目的是初始化各顶点的上一顶点,且都设为源节点
 
 
        Dim ss(num - 2) As Integer  '数组ss()用于存放除源节点以外的所有顶点的编号
        For Me.k = 0 To num - 2
            ss(k) = k
        Next
        '上面的循环目的是给数组ss()赋值,即除源节点以外的所有顶点编号
 
 
        '注:这里数组V(),l(),t(),ss()的大小之所以要用num-1,num-2主要是因为数组是从0开始计数的
 
     
        Dim nn As Integer  'n表示所有顶点个数,nn表示除源点外的顶点个数
        nn = ss.Length       '这里nn=6
 
        '*******************************初始化工作结束*************************
 
        Dim cont As Integer = 0
        Dim X() As Integer      '数组X()存放已经找到最短路的顶点,初始第一个为起点
        ReDim X(0)
        X(0) = startpoint - 1
 
        Dim i, j As Integer  '主体循环的循环变量
        Dim m As Integer   '用于中间变量
        For j = 0 To num - 2
            m = ss(0)
            For i = 0 To nn - 1
                If l(m) > l(ss(i)) Then
                    m = ss(i)
                    l(m) = l(ss(i)) '在当前一行距离中取最小值
                End If
            Next
 
            If l(m) = Inf Then  '如果当前行最小值是无穷大,则结束
            Else   '否则m点的最短路找到
                cont = cont + 1
                ReDim Preserve X(cont)
                X(cont) = m                   '这三句的作用是将符合条件的m加进数组X()中
 
                Array.Sort(X)
 
                Dim index As Integer = 0
                For i = 0 To V.Length - 1
                    If Array.IndexOf(X, V(i)) = -1 Then
                        ReDim Preserve ss(index)
                        ss(index) = V(i)
                        index += 1
                    End If
                Next
 
                Array.Sort(ss)
                '这里的循环是比较数组X()和数组V(),将属于数组V()而不属于数组X()的元素取出来,赋给动态数组ss()
                nn = ss.Length
 
            End If
 
            If X.Length = num Then
            Else
                For i = 0 To nn - 1           ' 以m为生长点,如果通过m点会更短,则更改当前最短距离
 
                    If l(ss(i)) > l(m) + w(m, ss(i)) Then
                        l(ss(i)) = l(m) + w(m, ss(i))
                        t(ss(i)) = m
                    End If
                Next
            End If
        Next
 
 
 
        Dim tt() As Integer
        ReDim tt(0)
        tt(0) = endpoint - 1        '动态数组tt()的作用是用来存放源到目的顶点最短路径上经过的节点
 
        Dim mm As Integer        '变量mm作为中间变量
        mm = endpoint - 1
 
        Dim cont_1 As Integer = 1
        For i = 0 To num - 1
            If mm = startpoint - 1 Then
 
            Else
                mm = t(mm)
                ReDim Preserve tt(cont_1)
                tt(cont_1) = mm
                cont_1 += 1
            End If
 
        Next
        Array.Reverse(tt)   '将数组tt反转排序
 
        For i = 0 To num - 1
            listbox1.Items.Add(l(i))                 'ListBox1存放起点到终点的最短路径值
        Next
 
        For i = 0 To num - 1
            listbox2.Items.Add(t(i) + 1)             'ListBox2存放起点到各个顶点最短路径上,各个顶点的上一节点
        Next
 
        For i = 0 To tt.Length - 1
            listbox3.Items.Add(tt(i) + 1)            'ListBox3存放起点到终点最短路径上经过的点
        Next
       
 
 
    End Sub
 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Me.Close()
    End Sub
 
End Class