0

I want to know an easy way to obtain a (Map + min-Heap) data structure in C++

I tried this:

struct Comp
{
    bool operator()(const pair<int,int>& y , const pair<int,int>& z)
    {
        return (y.second < z.second);
    }
};

priority_queue< pair<int,int> , map<int,int> , Comp > p;

now the problem I face is with re-initialisation since it is in priority_queue we can't just simply initialise like we do with maps.
The only way to insert element is

p.push(make_pair(value1,value2));

I have also tried to use simple maps instead of using it with priority_queue but the problem again is when I try to find the minimum element using min_element it returns the value instead of the key which is also required here.

Please suggest the fastest possible way to execute the problem. I also believe that there are ways possible beyond my knowledge.

Ryuzaki
  • 95
  • 1
  • 9
  • 1
    The second parameter of `priority_queue` "must satisfy the requirements of SequenceContainer, and its iterators must satisfy the requirements of RandomAccessIterator. Additionally, it must provide the following functions with the usual semantics: front() push_back() pop_back()" --http://en.cppreference.com/w/cpp/container/priority_queue . `std::map` meets none of these requirements. – Mooing Duck Aug 02 '16 at 20:20
  • Why do you think you want a map + min-heap? This is an [X,Y problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Mooing Duck Aug 02 '16 at 20:21
  • @Ryuzaki Do you want a way to change the values of an element (`pair `) within the priority queue? And you want a way to be able to index that element within the priority queue to change it? – Shubham Aug 02 '16 at 20:25
  • @MooingDuck , Sir I need it because I was implementing Dijkstra in a very optimised way in c++. – Ryuzaki Aug 03 '16 at 12:22
  • 1
    If you're doing dijkstra then you do want a min-heap (priority_queue). That cannot be done with a map. Let it use the default underlying type (vector). – Kenny Ostrom Aug 03 '16 at 12:25
  • @ShubhamBhattar, Sir I think the problem now is to find **index** from 'iterator'.Can this thing happen? – Ryuzaki Aug 03 '16 at 12:25
  • 1
    You do not want the index. You want the minimum, which you obtain from top/pop – Kenny Ostrom Aug 03 '16 at 12:26
  • 1
    And observe that though it is not a priority queue, a regular (ordered) map enforces the heap invariant and its minimum can be obtained using `std::begin(my_map)` – Rerito Aug 03 '16 at 12:47
  • 1
    I don't really understand what you are trying to achieve though. A regular priority queue is enough for Dijkstra, how do you want to optimize it? – Rerito Aug 03 '16 at 12:49

2 Answers2

0

No, you cannot index elements in a priority queue to change the values. You either have to implement the whole priority queue yourself with the changeKey() operation (which can be very optimised by the way), or do some other workaround.

I have implemented a priority queue with decreaseKey() operation for Prim's algorithm to calculate Minimum Spanning Trees. If you want to implement the priority queue then you can check my answer here or for some other workarounds check Gassa's answer here.

Community
  • 1
  • 1
Shubham
  • 2,847
  • 4
  • 24
  • 37
0

If you review the first comment, and follow the link to the documentation of priority_queue, then you have all the tools you need.

Let's suppose you already have an edge defined somewhere. Let's say

struct edge {
    int vertex1, vertex2;
    int weight;
    bool operator> (const edge &ref) const {return weight > ref.weight;}
};

You need a heap, which according to the docs should be based on vector or deque. I usually prefer vector, but I put deque here just for fun. The docs say use std::greater if you want a min-heap, therefore you also must implement edge::operator>

#include <queue>      // std::priority_queue and std::deque
#include <functional> // std::greater
typedef std::priority_queue<edge, std::deque<edge>, std::greater<edge> > djikstra_heap;

Now you are able to push edges and get the min.

edge e1{ 1, 2, 2 };
edge e2{ 1, 3, 4 };

djikstra_heap heap;
heap.push(e1);
heap.push(e2);
edge first_result = heap.top(); heap.pop();
Kenny Ostrom
  • 5,639
  • 2
  • 21
  • 30