我正在尝试实现一个数据结构,它是堆和无序映射的组合。 堆将保存图形节点,包含标识符和成本。 我使用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) insert:O(lg n)
如果我推出自己的堆,当我向上或向下执行冒泡时,我将更新地图中节点的位置,这将是微不足道的。在我这样做之前,我想确保在STL中无法做到这一点。
答案 0 :(得分:0)
如果将 edge 放入优先级队列而不是节点,那么您不需要更新节点功能,一切都变得容易了。
然后:
将初始顶点添加到集合中,并将其边缘添加到优先级队列
从优先级队列中删除最便宜的边缘。
如果E的顶点V之一不在树中,则将E和V添加到树中。 V进入您的设置。如果V对于不在集合中的节点有任何边缘,则将这些边缘添加到优先级队列。
返回第2步,直到队列为空。
答案 1 :(得分:0)
这个想法是从一个空的堆开始,并在进行过程中将顶点推入其中。我们可以多次将相同的顶点推入堆中,但是我们仍然可以正确地形成MST(使用父列表),并且总体复杂度仍然为O(E * log(V))。这样,我们不必实现decrease_key
函数。
一个人可以使用priority_queue
来实现。
但是,我使用push_heap
和pop_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;
}