【问题标题】:How to implement Prim's algorithm using STL ?如何使用 STL 实现 Prim 算法?
【发布时间】:2016-11-28 18:23:59
【问题描述】:

我正在尝试实现一个数据结构,它是堆和无序映射的组合。 堆将保存图形节点,包含标识符和成本。 我使用 min_extract 函数让节点在 log(n) 时间内展开。 [我正在使用算法中的 std::vector 和 std::make_heap 、 pop_heap 等实现堆]

无序映射将节点 , 位置保存在向量映射中。无序映射用于支持包含和更新节点功能。但是对于我来说,我需要节点与其在向量中的位置之间的映射,否则我不得不对项目进行线性搜索。

更令人担忧的是,我推送或弹出一个项目,并调用 push_heap 或 pop_heap,这将围绕向量中的节点移动,而我在地图中维护的位置最终会出错。

那么我该如何实现该功能,我可以在其中维护节点与其位置之间的映射。

    void push(T elem) // This will 0(n)... As the element has to be found
    {
        heapVec_.push_back(elem); // add tp vec

        std::push_heap<compar_> (heapVec_.begin() , heapVec_.end());
        // sort ? or just find in the vec ? 
        std::size_t pos = 0 ;

        // find position of the item in the vector
        std::find_if(heapVec_.begin() , heapVec_.end() , [&pos , &elem](const T& item)
                {

                    if(item == elem)
                    {
                        return true;
                    }
                    else
                    {
                        ++pos;
                    }
                });


        // add to map
        heapMap_.emplace_back(elem , pos); // how to keep track of the element where this object is added to ? 

    }   

我正在寻找的数据结构必须支持: 找到最小值:O(lg n) 包含:O(1) 更新节点:O(lg n) 插入:O(lg n)

如果我推出自己的堆,当我向上或向下做气泡时,我会更新地图中节点的位置,这将是微不足道的。在我这样做之前,我想确保我不能在 STL 中做到这一点。

【问题讨论】:

标签: c++ algorithm vector stl unordered-map


【解决方案1】:

如果您将 edges 放入优先级队列而不是节点,那么您就不需要 update-node 功能,一切都会变得容易得多。

  • 使用某种集合实现来跟踪树中的哪些顶点。
  • 使用优先级队列来维护可能的边的有序队列。

然后:

  1. 将初始顶点添加到集合中,并将其边添加到优先级队列中

  2. 从优先级队列中移除最便宜的边 E。

  3. 如果 E 的顶点 V 之一不在树中,则将 E 和 V 添加到树中。 V进入你的集合。如果 V 对不在集合中的节点有任何边,则将这些边添加到优先级队列中。

  4. 返回第 2 步,直到队列为空。

【讨论】:

    【解决方案2】:

    我们的想法是从一个空堆开始,并在我们继续进行时将顶点推入其中。我们可以将同一个顶点多次推入堆中,但我们仍然正确地形成了 MST(使用父列表)并且整体复杂度仍然保持 O( E * log(V) )。这样我们就不必实现decrease_key函数了。

    可以使用priority_queue 来实现这一点。 然而,我使用push_heappop_heap 函数实现了它:

    #include <iostream>
    #include <vector>
    #include<algorithm>
    #include<climits>
    using namespace std;
    void addEdge(vector<vector <pair<int, int> > >&adj, int u, int v, int w) 
    { 
        adj[u].push_back(make_pair(v, w)); 
        adj[v].push_back(make_pair(u, w)); 
    }
    
    int main(){
      vector<vector <pair<int, int> > >adj(9); // Taking a 9 node graph for testing.
      addEdge(adj, 0, 1, 4); 
      addEdge(adj, 0, 7, 8); 
      addEdge(adj, 1, 2, 8); 
      addEdge(adj, 1, 7, 11); 
      addEdge(adj, 2, 3, 7); 
      addEdge(adj, 2, 8, 2); 
      addEdge(adj, 2, 5, 4); 
      addEdge(adj, 3, 4, 9); 
      addEdge(adj, 3, 5, 14); 
      addEdge(adj, 4, 5, 10); 
      addEdge(adj, 5, 6, 2); 
      addEdge(adj, 6, 7, 1); 
      addEdge(adj, 6, 8, 6); 
      addEdge(adj, 7, 8, 7);
    
      vector<int> key(9, INT_MAX);
      vector<int> parent(9, -1);
      vector<bool> isInMST(9, false);
    
      key[0] = 0; // Source node is 0, its key value is also 0.
      vector<pair<int, int> > heap; // Vector named as heap.
      heap.push_back(make_pair(0, 0)); // No need to call make_heap as it has only 1 element.
    
      while(!heap.empty()){
        pair<int, int> temp = heap.front();
        pop_heap(heap.begin(), heap.end(), [ ] (pair<int, int> l, pair<int, int> r){
          return l.first > r.first;
        });
        heap.pop_back();
        int u = temp.second;
        isInMST[u] = true;
        for(int i=0; i<adj[u].size(); i++){
          int v = adj[u][i].first;
          int w = adj[u][i].second;
          if(!isInMST[v] && key[v] > w){
            key[v] = w;
            heap.push_back(make_pair(w, v));
            push_heap(heap.begin(), heap.end(), [ ] (pair<int, int> l, pair<int, int> r){
              return l.first > r.first;
            });
            parent[v] = u;
          }
        }
      }
    
      for (int i = 1; i < 9; i++) // Starting from 1, as 0 is source.
        cout << parent[i] << " - " << i << endl; // Print edges of MST using parent array.
    
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多