1

Explain to me how to construct a priority queue and why you have to construct that way as though the limit of my my experiences with priority queues is knowing what a queue is (I have never used one in my life).

When I'm looking at this website: http://comsci.liu.edu/~jrodriguez/cs631sp08/c++priorityqueue.html

priority_queue<Time, vector<Time>, CompareTime> pq;

I understand that Time is so that you have a queue of Times, Compare Time is what determines the priority of which a time is placed into the queue, but why does vector<Time> need to be in the constructor?

About Dijkstra: I'm implementing a graph as a vector of nodes, which each node containing a list of all its neighbors positions in that vector), so it looks something like this:

class Node {
  protected:
  string name;
  int value;
  list<int> nodes
}

How would I implement this part of Dijkstra:

for each vertex v in Graph:                                
    dist[v] := infinity ;                               
    previous[v] := undefined ;     

for dist[v] = infinity, I'm assuming I set the value of every node to infinity, but what variable would allow me to do that? And for previous[v], what does it mean by undefined?

Adrian Panasiuk
  • 7,249
  • 5
  • 33
  • 54
Jonathan Chiou
  • 349
  • 6
  • 15
  • for infinity checkout `limit.h` or `-1` or any other unused number/string identifier. if you works with doubles http://stackoverflow.com/a/8640726/1031417 – 0x90 Jun 07 '13 at 23:02
  • That Vector – Bojin Li Jun 07 '13 at 23:39

2 Answers2

3

In C++ int max value could be used as infinite

#include <limits>

then use

int imax = std::numeric_limits<int>::max();
Nick
  • 4,192
  • 1
  • 19
  • 30
  • So how would it look without std::whatever? max()? – Jonathan Chiou Jun 07 '13 at 23:17
  • @JonathanChiou Would depend on your system, but if `int` is `4` bytes then it's `(1<<31) - 1`, which is why using `limits` is better since you don't have to guess – jamylak Jun 07 '13 at 23:23
  • Oh, max gives me the max number for an integer. I need infinity, as one of the test cases in my assignment requires me to go past max() – Jonathan Chiou Jun 08 '13 at 00:33
  • @JonathanChiou In fact in real scenario you will never have an edge with value greater than max value of int – Nick Jun 08 '13 at 00:34
  • for djikstra's what does the line previous[v] <- undefined mean? – Jonathan Chiou Jun 08 '13 at 01:22
  • @NikolaMitev infinity does exist. It's just not an `int` but a floating point number. So this `std::numeric_limits::infinity();` should work as OP wants – Honza Brabec Jun 09 '13 at 13:56
3

Its a programming exercise (Aka you must have to implement everithing), or its a real program?

If is the last, checkout the Standard Library priority queue: http://en.cppreference.com/w/cpp/container/priority_queue

If, on the other hand, its really a learning exercise, after a bit googling you could found this: http://pages.cs.wisc.edu/~vernon/cs367/notes/11.PRIORITY-Q.html

I could write an introduction/explanation to priority_queues implementation (Max/Min heaps, push/pop operations, etc), but that paper has (I think) really good examples, explanations, and pictures.

EDIT: After seeing your answer to my question "its an exercise or a real program?". I prefer to write the entire answer here, with examples.

STEP1: Setup

std::priority_queue has three template parameters:

  • T: Obviously, the type of the items stored at the container.
  • The underlying container: As its name says, is the type of the underlying container used in the implementation. Its default value is std::vector<T>.
  • Comparer: Functor class that the priority_queue uses to compare items. Its default value is std::less<T> (So, by default, the std::priority_queue is a max priority queue). If you want a min priority queue (As in your case, the Dijkstra's algorithm) you must pass a comparer to do that. Normally, you implement binary operator > for your type, to make std::greater<T> functor work.

STEP2: Using std::priority_queue

So, if you have done the setup fine, you are ready to use std::priority_queue. It has three principal operations:

  • push(): Inserts a value in the piority_queue.
  • pop(): Removes the top of the priority queue.
  • top(): Returns a const reference to the element with maximum (Or minimum, depending on your comparer) priority stored at the priority_queue. Note that top() not remove, it is the work of pop().

Example:

#include <queue>
#include <iostream>

//User defined type. For this short example, a simple uint wrapper:
struct Foo
{
    unsigned int i;

    Foo(unsigned int _i) : i(_i) {}
};

//Implementation of operator> for class Foo, to make std::greater<Foo> work:
bool operator>(const Foo& f1 , const Foo& f2)
{
    return f1.i > f2.i;
}

int main()
{
    std::priority_queue<Foo,std::vector<Foo>,std::greater<Foo>> foo_min_priority_queue;

    foo_min_priority_queue.push(Foo(2));
    foo_min_priority_queue.push(Foo(1));
    foo_min_priority_queue.push(Foo(0));

    std::cout << foo_min_priority_queue.top().i << std::endl; //Prints 0 
    foo_priority_queue.pop();

    std::cout << foo_min_priority_queue.top().i << std::endl; //Prints 1 
    foo_min_priority_queue.pop();

    std::cout << foo_min_priority_queue.top().i << std::endl; //Prints 2 
    foo_min_priority_queue.pop();

    return 0;
}

References:

Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • real program, I need to know how to use the STL priority queue – Jonathan Chiou Jun 08 '13 at 00:07
  • @JonathanChiou I edited the answer with complete explanations and an example. – Manu343726 Jun 08 '13 at 19:41
  • I don't think it's possible to use STL's priority queue for Dijkstra's algorithm, as the algorithm requires the `decrease-key` abstract operation on the queue. STL's priority queue provides neither that, nor the ability to remove arbitrary element to update its priority and insert it back again. For efficient Dijkstra's algorithm implementation, a Fibonacci heap would be a good choice. Altough a d-ary heap is simple enough to implement yourself (using an array). – Alexei Sholik Jul 06 '13 at 23:11
  • 1
    @android not really. You can still insert a new element into the priority queue even when it **exists** in the queue. In practice I never came across major performance degradation for this. – phoeagon Jul 07 '13 at 03:24
  • And I don't think a comparator is necessarily. By default `priority_queue` returns the maximal element so you just need to store the *negated result* of the distance. – phoeagon Jul 07 '13 at 03:24
  • @phoeagon How does it know it exists? Does it use `operator==`? What if I store pointers, will it compare pointers? The usability of `priority_queue` is very limited. If you need any non-basic operations or the ability to merge two queues, you're screwed. I bet Boost has something more functional. – Alexei Sholik Jul 07 '13 at 09:27
  • @android you don't need to know whether it exists. Just insert it into the `priority_queue`. Maybe there's performance degradation maybe not, I'm not sure of those I never came across myself. – phoeagon Jul 07 '13 at 14:31