c#中的Dijkstras算法

时间:2012-10-18 18:38:38

标签: c# algorithm dijkstra

构建一个从头开始使用Dijkstras alg的图表控件。我试图了解这个算法,在网上搜索。我想我终于明白了,但是我的代码无法正常工作。希望有人可以看一看,看看他们是否知道与它有什么关系......

我会粘贴三种方法,因为我认为这是可能需要的所有方法。

对于初学者,我会说我创建了自己的Vertex数据类型。它包含节点的ID,X和Y,状态字符串,以及也是顶点数据类型的父节点和整数的距离。

    //function to populate lists with all the vertices on the graph
    private List<Vertex> getNodes()
    {
        myVertices.Clear();
        //get all non-dg nodes in list
        for (int i = 0; i < chtGraph.Series[0].Points.Count; i++)
        {
            Vertex vertice = new Vertex(chtGraph.Series[0].Points[i]["ID"], (float)chtGraph.Series[0].Points[i].XValue, (float)chtGraph.Series[0].Points[i].YValues[0], "UNVISITED", Convert.ToInt32(chtGraph.Series[0].Points[i].Label), double.PositiveInfinity, null);
            myVertices.Insert(i, vertice);
        }

        //get all dg nodes in list
        for (int i = 0; i < chtGraph.Series[1].Points.Count; i++)
        {
            Vertex vertice = new Vertex(chtGraph.Series[1].Points[i]["ID"], (float)chtGraph.Series[1].Points[i].XValue, (float)chtGraph.Series[1].Points[i].YValues[0], "UNVISITED", Convert.ToInt32(chtGraph.Series[1].Points[i].Label), double.PositiveInfinity, null);
            myVertices.Insert(i, vertice);
        }
        return myVertices;
    }

    //function to return to a list all the adjacents for a specified node.  Excludes parent node
    private List<Vertex> checkAdjacents(Vertex node, int intTransPower)
    {
        List<Vertex> Adjacents = new List<Vertex>();
        int distance;

        for (int i = 0; i < myVertices.Count; i++)
        {
            if (node.id != myVertices[i].id)
            {
                distance = calcDistance(node.x, node.y, myVertices[i].x, myVertices[i].y);

                if (distance <= intTransPower)
                {
                    if (rdbTotalLength.Checked)
                    {
                        myVertices[i].distance = distance;
                    }
                    else if (rdbPathEnergy.Checked)
                    {
                        myVertices[i].distance = getCost(node, myVertices[i]);
                    }
                    else
                    {
                        myVertices[i].distance = 1;
                    }

                    myVertices[i].parent = node;
                    Adjacents.Add(myVertices[i]);

                    foreach (Vertex p in openList)
                    {
                        if (myVertices[i].id == p.id)
                        {
                            p.distance = myVertices[i].distance;
                            p.parent = myVertices[i].parent;
                        }
                    }
                }
            }
        }

        return Adjacents;

    }

这里是dijkstras ....目前工作不正常,我无法理解。

private void dijkstra(Vertex start, Vertex end)
    {

        openList.Clear();

        //populate two lists with all the nodes in the graph
        openList = getNodes();
        myVertices = getNodes();

        //adjacents list for each vertex visited
        List<Vertex> adjacents = new List<Vertex>();

        //final list that is populated with the final path of vertices
        List<Edge> shortestPath = new List<Edge>();

        //used in calculating adjacent nodes.  If distance is greater than transpower, then nodes are not connected
        int intTransPower = Convert.ToInt32(txtTransPower.Text);

        //set current vertex as the starting node
        Vertex current = start;

        //set initially to false
        bool pathFound = false;

        //find the starting node from the list of all vertices.  Set it's distance to 0
        foreach (Vertex p in openList)
        {
            if (p.id == current.id)
            {
                p.status = current.status;
                p.distance = 0;
            }
        }
        foreach (Vertex p in myVertices)
        {
            if (p.id == current.id)
            {
                p.status = current.status;
                p.distance = 0;
            }
        }

        //reorder the list to bring the starting node to the first element
        openList = openList.OrderBy(h => h.distance).ToList();

        //openList.Add(current);
        //this.insert(openList, current, true);

        // Repeat while the openlist is not empty and you haven't reached the end
        while (openList.Count > 0)
        {
            //remove node at element 0.  Sorted by smallest distance so it always gets removed first
            current = openList[0];
            openList.RemoveAt(0);

            //if the current node = the ending node, then we have found the path.  Break loop and build the final path.
            if (current.id == end.id)
            {
                pathFound = true;
                break;
            }

            //collect up all the adjacent nodes for the current vertex
            //does NOT include the current vertex we are on
            adjacents = checkAdjacents(current, intTransPower);

            foreach (Vertex v in adjacents)
            {
                float alt =  (float)current.distance + calcDistance(current.x, current.y, v.x, v.y);
                Convert.ToInt32(alt);

                if (alt < v.distance)
                {
                    v.distance = alt;
                    v.parent = current;
                    for (int i = 0; i < openList.Count; i++)
                    {
                        if (v.id == openList[i].id)
                        {
                            openList[i].distance = alt;
                            openList[i].parent = current;
                        }
                    }
                }

            }
            openList = openList.OrderBy(h => h.distance).ToList();
        }

        if (pathFound)
        {
            // collect path
            this.foundPath.Clear();
            Vertex last = current;
            while (current != start && current != null)
            {
                this.foundPath.Add(current);
                if (current.parent == last)
                    break;
                last = current;
                current = current.parent;
            }
            this.foundPath.Add(current);
        }

    }

1 个答案:

答案 0 :(得分:-1)

我有这种方法,但它是更大实现的一部分:

public static IDigraph DijkstrasAlgorithm(IDigraph g, int s)
        {
            //Collect number of vertices
            int num1 = g.NumberOfVertices;

            //create an array for vertices
            Entry[] entryArray1 = new Graphos.Algorithms.Entry[num1];

            //for each vertice create new instance for entry of edges
            for (int num2 = 0; num2 < num1; num2++)
            {
                entryArray1[num2] = new Graphos.Algorithms.Entry(false, 0x7fffffff, 0x7fffffff);
            }
            //set vertice origin with distance 0.
            entryArray1[s].distance = 0;

            //create a list for edges
            PriorityQueue queue1 = new BinaryHeap(g.NumberOfEdges);

            //create initial nodes in edges list
            queue1.Enqueue(new Association(0, g.GetVertex(s)));

            //while list is not empty
            while (!queue1.IsEmpty)
            {
                //creates an association
                Association association1 = (Association)queue1.DequeueMin();

                //attributes the vertice
                IVertex vertex1 = (IVertex)association1.Value;

                //if connection is known
                if (!entryArray1[vertex1.Number].known)
                {
                    //checks as known
                    entryArray1[vertex1.Number].known = true;

                    //foreach edge founded
                    foreach (Edge edge1 in vertex1.EmanatingEdges)
                    {
                        //creates the vertex that is being used
                        IVertex vertex2 = edge1.MateOf(vertex1);

                        //catches the weight since vertice in link
                        int num3 = entryArray1[vertex1.Number].distance + ((int)edge1.Weight);

                        //se o peso da ponte for menor que o peso maximo
                        if (entryArray1[vertex2.Number].distance > num3)
                        {
                            //Peso maximo é atualizado para o peso da ponte
                           entryArray1[vertex2.Number].distance = num3;

                            //Define o vértice vizinho 
                            entryArray1[vertex2.Number].predecessor = vertex1.Number;

                           //adiciona o vértice com seu vizinho e o peso entre eles na lista
                            queue1.Enqueue(new Association(num3, vertex2));
                        }
                    }
                }
            }
            //Á este ponto, todas as associações foram feitas

            //Cria o objeto grafo como uma lista baseado no numero de vertices
            IDigraph digraph1 = new DigraphAsLists(num1);

            //Para cada vértice
            for (int num4 = 0; num4 < num1; num4++)
            {
                //adiciona o vertice da lista no grafo
                digraph1.AddVertex(num4, entryArray1[num4].distance);
            }

            //para cada vertice
            for (int num5 = 0; num5 < num1; num5++)
            {
                //Se não for o ponto de origem
                if (num5 != s)
                {
                    //adiciona a aresta(origem,destino baseado no vizinho)
                    digraph1.AddEdge(num5, entryArray1[num5].predecessor);
                }
            }
            //retorna o grafo
            return digraph1;
        }