Why does Dijkstra's Algorithm use a heap (priority queue)?

后端 未结 4 695
余生分开走
余生分开走 2021-02-07 05:33

I have tried using Djikstra\'s Algorithm on a cyclic weighted graph without using a priority queue (heap) and it worked.

Wikipedia states that the original implementatio

4条回答
  •  别那么骄傲
    2021-02-07 05:48

    I had the exact same doubt and found a test case where the algorithm without a priority_queue would not work.

    Let's say I have a Graph object g, a method addEdge(a,b,w) which adds edge from vertex a to vertex b with weight w.

    Now, let me define the following graph :-

       Graph g 
       g.addEdge(0,1,5) ; 
       g.addEdge(1,3,1) ; 
       g.addEdge(0,2,2) ; 
       g.addEdge(2,1,1) ; 
       g.addEdge(2,3,7) ; 
    

    Now, say our queue contains the nodes in the following order {0,1,2,3 } So, node 0 is visited first then node 1 is visited.

    At this point of time the dist b/w 0 and 3 is computed as 6 using the path 0->1->3, and 1 is marked as visited.

    Now node 2 is visited and dist b/w 0 and 1 is updated to the value 3 using the path 0->2->1, but since node 1 is marked visited, you cannot change the distance b/w 0 and 3 which (using the optimal path) (`0->2->1->3) is 4.

    So, your algorithm fails without using the priority_queue.

    It reports dist b/w 0 and 3 to be 6 while in reality it should be 4.

    Now, here is the code which I used for implementing the algorithm :-

                class Graph
            {
                public: 
                    vector nodes ; 
                    vector > > edges ; 
                    void addNode() 
                    {
                        nodes.push_back(nodes.size()) ; 
                        vector > temp ; edges.push_back(temp);
                    }
                    void addEdge(int n1, int n2, int w)
                    {
                        edges[n1].push_back(make_pair(n2,w)) ; 
                    }
                    pair, vector > shortest(int source) // shortest path djkitra's
                    {
                        vector dist(nodes.size()) ; 
                        fill(dist.begin(), dist.end(), INF) ; dist[source] = 0 ; 
                        vector pred(nodes.size()) ; 
                        fill(pred.begin(), pred.end(), -1) ; 
                        for(int i=0; i<(int)edges[source].size(); i++)
                        {
                            dist[edges[source][i].first] = edges[source][i].second ; 
                            pred[edges[source][i].first] = source  ; 
                        }
                        set > pq ; 
                        for(int i=0; i<(int)nodes.size(); i++)
                            pq.insert(make_pair(dist[i],i)) ; 
                        while(!pq.empty())
                        {
                            pair item = *pq.begin() ; 
                            pq.erase(pq.begin()) ; 
                            int v = item.second ; 
                            for(int i=0; i<(int)edges[v].size(); i++)
                            {
                                if(dist[edges[v][i].first] > dist[v] + edges[v][i].second)
                                {
                                    pq.erase(std::find(pq.begin(), pq.end(),make_pair(dist[edges[v][i].first],edges[v][i].first))) ; 
                                    pq.insert(make_pair(dist[v] + edges[v][i].second,edges[v][i].first)) ; 
                                    dist[edges[v][i].first] = dist[v] + edges[v][i].second ; 
                                    pred[i] = edges[v][i].first ; 
                                }
                            }
                        }
                        return make_pair(dist,pred) ; 
                    }
        
        pair, vector > shortestwpq(int source) // shortest path djkitra's without priority_queue 
                {
                    vector dist(nodes.size()) ; 
                    fill(dist.begin(), dist.end(), INF) ; dist[source] = 0 ; 
                    vector pred(nodes.size()) ; 
                    fill(pred.begin(), pred.end(), -1) ; 
                    for(int i=0; i<(int)edges[source].size(); i++)
                    {
                        dist[edges[source][i].first] = edges[source][i].second ; 
                        pred[edges[source][i].first] = source  ; 
                    }
                    vector > pq ; 
                    for(int i=0; i<(int)nodes.size(); i++)
                        pq.push_back(make_pair(dist[i],i)) ; 
                    while(!pq.empty())
                    {
                        pair item = *pq.begin() ; 
                        pq.erase(pq.begin()) ; 
                        int v = item.second ; 
                        for(int i=0; i<(int)edges[v].size(); i++)
                        {
                            if(dist[edges[v][i].first] > dist[v] + edges[v][i].second)
                            {
                                dist[edges[v][i].first] = dist[v] + edges[v][i].second ; 
                                pred[i] = edges[v][i].first ; 
                            }
                        }
                    }
                    return make_pair(dist,pred) ; 
                }
    

    As expected the results were as follows :-

    With priority_queue
    0
    3
    2
    4

    Now using without priority queue
    0
    3
    2
    6

提交回复
热议问题