I am trying to create a program that takes N random nodes from user input and creates a random integer that is put into a binary tree and then copied into a priority queue. The integer becomes the key for each node and another integer counts the frequency of the key. I run into issues when I copy into the priority queue because I get duplicates and I need to remove them. I tried to create a set through the node constructor but I get the error above in the .cpp file.
#include <iostream>
#include <random>
#include <ctime>
#include <queue>
#include <set>
#include <functional>
#include <algorithm>
#include<list>
#include "Q7.h"
using namespace std;
int main()
{
node * root=NULL;
node z;
int n,v;
vector<int> first;
vector<int>::iterator fi;
default_random_engine gen(time(NULL));
cout<<"how many values? "; cin>>n;
for(int i=0; i<n; i++)
{ (v=gen()%n);
first.push_back(v);
if(root==NULL){root = node(set(v));}///This is where I get the error!!
else{
root->addnode(v);
}
}
z.unsortedRemoveDuplicates(first);
cout<<"Binary Tree in a depth first manner with Duplicates removed!"<<endl;
for ( fi = first.begin() ; fi != first.end(); ++fi{cout<<"Node "<<*fi<<endl;}
cout<<"-------------------"<<endl;
root->display();
cout<<"-------------------"<<endl;
cout<<"-------------------"<<endl;
root->display_Queue1();
cout<<"-------------------"<<endl;
return 0;
}
my .h file
class node
{
public:
node(){left=NULL; right=NULL; ct = 1;}
node set(int v) {val = v; left=NULL; right=NULL; ct=1;}
node (int Pri, int cat)
: val(Pri), ct(cat) {}
friend bool operator<(//sorts queue by lowest Priority
const node& x, const node& y) {
return x.val < y.val;
}
friend bool operator>(//sorts queue by greatest Priority
const node& x, const node& y) {
return x.ct > y.ct;
}
friend ostream&//prints out queue later
operator<<(ostream& os, const node& Pri) {
return os <<"my value = "<<Pri.val<<" occured "<<Pri.ct<<" times";
}
int unsortedRemoveDuplicates(vector<int>& numbers)
{
node set<int> seenNums; //log(n) existence check
auto itr = begin(numbers);
while(itr != end(numbers))
{
if(seenNums.find(*itr) != end(seenNums)) //seen? erase it
itr = numbers.erase(itr); //itr now points to next element
else
{
seenNums.insert(*itr);
itr++;
}
}
return seenNums.size();
}
priority_queue<node, vector<node>, greater<node> > pq;
priority_queue<node, vector<node>, less<node> > pq1;
void addnode(int v)
{
if(v==val){ct++;}
pq.emplace(node (set (v)));///No error here for set with constructor why??
pq.emplace(node (set (v)));
if(v<val)
{
if(left==NULL){left=new node(set(v));
}
else{left->addnode(v);
}
}
else
{
if(right==NULL){right = new node (set(v));
}
else{right->addnode(v);
}
}
}
int display()
{
if(left!=NULL){left->display();}
cout<<"frequency "<<ct<<" value"<<val<<endl;
if(right!=NULL){right->display();}
}
void display_Queue()
{
cout << "0. size: " << pq.size() << '\n';
cout << "Popping out elements from Pqueue..."<<'\n';
while (!pq.empty())
{
cout << pq.top() << endl;
pq.pop();
}
cout << '\n';
}
void display_Queue1()
{
cout << "0. size: " << pq1.size() << '\n';
cout << "Popping out elements from Pqueue..."<<'\n';
while (!pq1.empty())
{
cout << pq1.top() << endl;
pq1.pop();
}
cout << '\n';
}
private:
int val; ///value in that node
int ct;
///ct = count of that value
node * left;
node * right;
};
Congratulations, with this line:
root = node(set(v));
You have discovered why people here often say to avoid using using namespace std;. This is being interpreted as:
root = static_cast<node>(std::set(v));
Instead of what you want, which might be:
root = new node();
root->set(v);
First, note that we need to use new as we are creating a new node, not trying to cast a node to a node, which would have also given another compiler error about trying to assign a value to a pointer.
Next, note that you don't get the error in the header file as there is no using namespace std; there, and since it is in a member function, the line:
void node::addnode(int v)
{
//...
pq.emplace(node (set (v)));///No error here for set with constructor why??
//...
}
Is interpreted as:
pq.emplace(static_cast<node>(this->set(v)));
However, is this what you really want to do?
Furthermore, I would change the constructors to be:
public:
node (int Pri = 0, int cat = 1)
: val(Pri), ct(cat), left(NULL), right(NULL) {}
// DELETED node (int Pri, int cat)
Thus you can do:
root = new node(v);
And it will work as I think you expect it to.
Related
I am trying to implement kruskal's algo. togather with bfs and dfs. i wrote my code to print the adjancey list and to show the bfs and dfs and now i am facing problem with writing the code for kruskal's algorithm i kind of newbie in using maps and templates. i don't know how to pass the values in the kruskals algorithm and i m constantly getting errors.
here is the code that i have written.
#include<iostream>
#include<map>
#include<queue>
#include<list>
#include<cstring>
#include<algorithm>
using namespace std;
template<typename T>
class Graph{
private:
map<T,list<pair<T,int>>> l;
void DFSHelper(T node,map<T,bool> &visited){
cout<<node<<" -> ";
visited[node]=true;
for(auto neighbours:l[node]){
if(!visited[neighbours.first]){
DFSHelper(neighbours.first,visited);
}
}
}
public:
void add(T A,T B,bool bi,int wi){
l[A].push_back(make_pair(B,wi));
if(bi == true){
l[B].push_back(make_pair(A,wi));
}
}
void print(){
for(auto c:l){
int c1 = c.first;
list<pair<int,int>> n = c.second;
cout<<c1<<" -> ";
for(auto k:n){
int dest = k.first;
int dist = k.second;
cout<<dest<<"("<<dist<<") ";
}
cout<<endl;
}
}
void bfs(T src){
map<T,bool> visited;
queue<T> q;
q.push(src);
visited[src] = true;
while(!q.empty()){
T node = q.front();
q.pop();
cout<<node<<" -> ";
for(auto children:l[node]){
if(!visited[children.first]){
visited[children.first]=true;
q.push(children.first);
}
}
}
}
void dfs(T src){
map<T,bool> visited;
int component = 1;
DFSHelper(src,visited);
}
void cmp(T src,T end){
return src.second.second<end.second.second;
}
void kruskals(){
}
};
int main(){
Graph<int> g;
g.add(1,2,true,20);
g.add(1,3,true,30);
g.add(2,4,true,50);
g.add(3,4,true,10);
g.add(4,5,true,60);
g.add(5,1,false,35);
g.print();
cout<<endl;
cout<<"BFS :- ";
g.bfs(1);
cout<<endl;
cout<<"DFS :- ";
g.dfs(1);
g.kruskals();
}
Your graph appears to be directed due to the uni-directional edge 5->1. Kruskal's algorithm only works for undirected graphs. (Why?)
In Kruskal's algorithm you need the edges sorted in non-decreasing order of edge-weights. Hence you can either maintain an extra data structure alongwith the map l and insert to it in the add() function or create it in the kruskals() function itself.
Next you need a data structure to query if any two nodes of the graph belong to two different components or not. Here two nodes are said to be in the same component if you can reach one node to the other by only considering edges encountered till that particular iteration of the Kruskal's algorithm. A Disjoint Set Union can do that efficiently.
Here is an implementation, where I use the set edge_weights to store the edges sorted by weight:
#include<iostream>
#include<map>
#include<queue>
#include<list>
#include<cstring>
#include<algorithm>
#include <set> // Added
using namespace std;
template<typename T>
class DisjointSetUnion {
map<T, T> parent;
map<T, int> sz; // stores sizes of component
public:
void make_set(T v) {
parent[v] = v;
}
T find_set(T x) {
if(x != parent[x]) parent[x] = find_set(parent[x]);
return parent[x];
}
void merge_sets(T x, T y) {
int px = find_set(x), py = find_set(y);
if(sz[px] > sz[py]) parent[py] = px;
else parent[px] = py;
if(sz[py] == sz[px]) sz[py]++;
}
};
template<typename T>
class Graph{
private:
map<T,list<pair<T,int>>> l;
set<pair<int, pair<T, T>>> edge_weights; // no parallel (or duplicate) edges exist
void DFSHelper(T node,map<T,bool> &visited){
cout<<node<<" -> ";
visited[node]=true;
for(auto neighbours:l[node]){
if(!visited[neighbours.first]){
DFSHelper(neighbours.first,visited);
}
}
}
public:
void add(T A,T B,bool bi,int wi){
l[A].push_back(make_pair(B,wi));
if(bi == true){
l[B].push_back(make_pair(A,wi));
edge_weights.insert(make_pair(wi, make_pair(A, B))); // Added
}
}
void print(){
for(auto c:l){
int c1 = c.first;
list<pair<int,int>> n = c.second;
cout<<c1<<" -> ";
for(auto k:n){
int dest = k.first;
int dist = k.second;
cout<<dest<<"("<<dist<<") ";
}
cout<<endl;
}
}
void bfs(T src){
map<T,bool> visited;
queue<T> q;
q.push(src);
visited[src] = true;
while(!q.empty()){
T node = q.front();
q.pop();
cout<<node<<" -> ";
for(auto children:l[node]){
if(!visited[children.first]){
visited[children.first]=true;
q.push(children.first);
}
}
}
}
void dfs(T src){
map<T,bool> visited;
int component = 1;
DFSHelper(src,visited);
}
void cmp(T src,T end){
return src.second.second<end.second.second;
}
void kruskals(){
DisjointSetUnion<int> dsu;
// make singleton components of each node
for(auto it: l) {
T u = it.first;
dsu.make_set(u);
}
// iterate over all edges in sorted order
for(auto ed: edge_weights) {
int w = ed.first;
T u = ed.second.first, v = ed.second.second;
// if they belong to different components then they are
// part of the MST, otherwise they create a cycle
if(dsu.find_set(u) != dsu.find_set(v)) {
// this edge is part of the MST, do what you want to do with it!
cout << "(" << u << "," << v << "," << w << "), ";
// merge the two different components
dsu.merge_sets(u, v);
}
}
}
};
int main(){
Graph<int> g;
g.add(1,2,true,20);
g.add(1,3,true,30);
g.add(2,4,true,50);
g.add(3,4,true,10);
g.add(4,5,true,60);
// Removed unidirectional edge below
// g.add(5,1,false,35);
g.print();
cout<<endl;
cout<<"BFS :- ";
g.bfs(1);
cout<<endl;
cout<<"DFS :- ";
g.dfs(1);
cout << endl;
cout << "Edges in MST (u,v,w): ";
g.kruskals();
cout << endl;
}
i have a cpp problem and i don't know whats wrong.. maybe you can help me :).
I'm trying to implement a data structure for a graph. In this graph i will connect some nodes, which have a small euclidean distance, but at the second iteration, my iterator will point to 0x0. This case appears only, if i give the distance of those two nodes to std::cout. Here is my code:
for(vector<Node*>::iterator n1 = g->getNodes().begin(); n1 != g->getNodes().end(); ++n1)
{
for(vector<Node*>::iterator n2 = g->getNodes().begin(); n2 != g->getNodes().end(); ++n2)
{
if(*n2 == 0)
{
// This will be entered after the first iteration of n2.
cout << "n2 null" << endl;
continue;
}
double distance = (*n1)->getDistance(*n2); // just euclidean distance
if(distance <= minDistance)
{
// This works fine:
cout << "(" << *n1 << "," << *n2 << ") << endl;
// This brings me a "Segmentation fault"
cout << "(" << *n1 << " , " << *n2 << ") -> " << distance << endl;
}
}
}
Is this owed by the nested loops? Can any body tell me my fault? Thanks a lot!
EDIT: Here is some more code:
node.h
#ifndef NODE_H_
#define NODE_H_
#include <vector>
#include <iostream>
#include <limits>
#include <math.h>
using namespace std;
class Node
{
private:
int x, y, z;
public:
Node(int x, int y, int z) : x(x), y(y), z(z)
{
}
inline int getX() { return x; }
inline int getY() { return y; }
inline int getZ() { return z; }
inline double getDistance(Node* other)
{
return sqrt(pow(x-other->getX(), 2) + pow(y-other->getY(), 2) + pow(z-other->getZ(), 2));
}
};
#endif
graph.h
#ifndef GRAPH_H_
#define GRAPH_H_
#include <vector>
#include "node.h"
using namespace std;
class Graph
{
private:
vector<Node*> nodes;
public:
~Graph()
{
while(!nodes.empty())
{
delete nodes.back(), nodes.pop_back();
}
}
inline vector<Node*> getNodes() { return nodes; }
inline int getCountNodes() { return nodes.size(); }
bool createNode(int x, int y, int z)
{
nodes.push_back(new Node(x, y, z));
return true;
};
#endif
main.cc
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
#include "model/graph.h"
using namespace std;
int main()
{
Graph *g = new Graph();
int nodeDistance = 100;
for(int z = 0; z <= 300; z += nodeDistance)
{
for(int x = 0; x <= 500; x += nodeDistance)
{
for(int y = 0; y <= 300; y += nodeDistance)
{
g->createNode(x, y, z);
}
}
}
for(vector<Node*>::iterator n1 = g->getNodes().begin(); n1 != g->getNodes().end(); ++n1)
{
for(vector<Node*>::iterator n2 = g->getNodes().begin(); n2 != g->getNodes().end(); ++n2)
{
if(*n2 == 0)
{
// This will be entered after the first iteration of n2.
cout << "n2 null" << endl;
continue;
}
double distance = (*n1)->getDistance(*n2); // just euclidean distance
if(distance <= nodeDistance)
{
// This works fine:
cout << "(" << *n1 << "," << *n2 << ") << endl;
// This brings me a "Segmentation fault"
cout << "(" << *n1 << " , " << *n2 << ") -> " << distance << endl;
}
}
}
delete g;
return 0;
}
One major issue is that your getNodes function returns a copy of a vector, not the original vector. Therefore your iterators you use in the loops are not iterating over the same vector.
Instead, the iterators you're using in the nested loops are iterating over 4 different (but equivalent) vectors instead of the actual vector from the object in question.
There is nothing wrong in returning a copy of a vector in general. However when you do this, you have to make sure you call such a function if you really want a copy, and not the same vector. Using the getNodes function as you used it is not a valid usage in terms of what you are trying to accomplish.
The error is here:
inline vector<Node*> getNodes() { return nodes; }
The fix:
inline vector<Node*>& getNodes() { return nodes; }
The latter ensures that a reference to the actual vector in question is returned, not a copy of the actual vector. You can add an additional function that returns the vector as a copy if you want to still have the functionality available.
I was trying to build my own binary search tree. However , my tree is not getting built. Please see code below and help.
#include<iostream>
#include<string>
using namespace std;
class Binarytree
{
private:
struct node
{
int data;
node *left;
node *right;
};
node *root;
public:
Binarytree();
void insertdata(node*,int);
void deletedata();
void printdata(node*);
void userprint(char);
void getdata(int);
};
Binarytree::Binarytree()
{
root=NULL;
cout<<"Setting root as NULL"<<endl;
}
void Binarytree::insertdata(node* temp3,int temp)
{ cout << "in insert data"<<endl;
node Dummy=node();
Dummy.data=temp;
Dummy.left=NULL;
Dummy.right=NULL;
cout << "Data To be inserted is "<<temp <<endl;
if (temp3 == NULL)
{ cout<<"Found NULL ROOT"<<endl;
temp3=&Dummy;
cout << "Entered a Data in tree"<<endl;
cout<<"Data in root"<<root->data<<endl;
}
else if (temp3->data > temp)
{ cout<<"Making a Left Recursive Call"<<endl;
insertdata(temp3->left,temp);
}
else
{ cout<<"Making a right Recursive Call"<<endl;
insertdata(temp3->right,temp);
}
}
void Binarytree::getdata(int check)
{ cout <<"in getdata"<<endl;
cout << "before insertdata"<<endl;
insertdata(root,check);
}
void Binarytree::printdata(node* printrt)
{
if (printrt ==NULL)
cout << "Nothing to print";
else
{ cout << printrt->data << endl;
printdata(printrt->left);
printdata(printrt->right);
}
}
void Binarytree::userprint(char in)
{ node* data;
data=root;
if (in == 'Y' || in == 'y')
printdata(data);
}
void main()
{ Binarytree element=Binarytree();
int userdata,i=0;
bool check = true;
while(check)
{ cout <<"Please Enter your Data"<<endl;
cin >> userdata;
element.getdata(userdata);
cout<<"FUnction returned to main"<<endl;
i++;
if(i==5)
check=false;
}
element.userprint('Y');
}
The very first value is not getting inserted in root pointer. I know there are lots of code available for doing this but if i don't code it my own I feel my learning will be limited.
So please help in figuring error in this code.
Having really tried to compile and there might be other problems... but
change
void Binarytree::insertdata(node* temp3,int temp)
to
void Binarytree::insertdata(node* &temp3,int temp)
so that the node created inside insertdata really modifies the outside pointer.
and change
node Dummy=node();
Dummy.data=temp;
Dummy.left=NULL;
Dummy.right=NULL;
to
node *Dummy=new node();
Dummy->data=temp;
Dummy->left=NULL;
Dummy->right=NULL;
As I said there might be other problems... you should worry about deleting nodes and all that...
Alternative you could create nodes outside of insertdata() and keep the same signature.
Anyway, good luck
The root cause (if you'll pardon the pun) is the way you're adding things to the root of the tree. Your code creates a temporary variable called Dummy on the stack and then takes its address. That's the first mistake because that temporary variable gets destroyed when the function ends.
The second problem is that in order to change the value of a pointer that you pass to a function, you have to pass a pointer to a pointer. In other words, your member function that was insertdata(node *, int) must become insertdata(node **, int)if you want to actually change the passed pointer rather than just a local copy as your original code had done.
To illustrate that fact, try this code.
#include <iostream>
int Y = 99;
void makeitsix(int n) {
n = 6;
}
void pointToY(int *ptr) {
ptr = &Y;
}
int main()
{
int x = 5;
int *p = &x;
std::cout << "x = " << x << ", *p = " << *p << std::endl;
makeitsix(x);
pointToY(p);
std::cout << "x = " << x << ", *p = " << *p << std::endl;
return 0;
}
When makeitsix() gets called, it's only the local copy of n that is altered, and not the value of 5 that was originally passed in. Similarly, ptr in the pointToY() function is only altering a local copy of ptr and not p that was used to call the function from within main(). If it were not so, an invocation such as makeitsix(3) would lead to some very strange effects!
I took the liberty of changing things somewhat in your code to make it a little cleaner, including
giving the node structure its own constructor
creating an extractor for the Binarytree
removing the various diagnostic printout statements (for brevity)
making the tree printout look more like a tree with the root to the left and the branches extending rightward
made some member functions private
and a few other minor things. The complete working code is below:
#include<iostream>
#include<string>
class Binarytree
{
private:
struct node
{
node(int d=0) : data(d), left(NULL), right(NULL) {};
int data;
node *left;
node *right;
};
node *root;
void insertdata(node**,int);
std::ostream& printdata(std::ostream &out, node*, int depth=0);
public:
Binarytree() : root(NULL) {};
std::ostream &printTo(std::ostream &out);
void insert(int);
};
void Binarytree::insertdata(node** temp3,int temp)
{
node *Dummy=new node(temp);
if (*temp3 == NULL) {
*temp3=Dummy;
} else if ((*temp3)->data > temp) {
insertdata(&((*temp3)->left),temp);
} else {
insertdata(&((*temp3)->right),temp);
}
}
void Binarytree::insert(int check)
{
insertdata(&root,check);
}
std::ostream &Binarytree::printdata(std::ostream &out, node* printrt, int depth)
{
if (printrt != NULL)
{
printdata(out, printrt->left, depth+1);
for (int i = 0; i < depth; ++i)
out << '\t';
out << printrt->data << std::endl;
printdata(out, printrt->right, depth+1);
}
return out;
}
std::ostream &Binarytree::printTo(std::ostream &out)
{
return printdata(out, root);
}
std::ostream &operator<<(std::ostream &out, Binarytree &b)
{
return b.printTo(out);
}
int main()
{
Binarytree element;
int userdata,i=0;
bool check = true;
while(check)
{
std::cout << "Please Enter your Data" << std::endl;
std::cin >> userdata;
element.insert(userdata);
i++;
if(i==5)
check=false;
}
std::cout << "Tree:\n" << element << std::endl;
return 0;
}
I'm building a huffman coding program and when I try and run the code I have so far it just gives me a warning that the freq map object .begin() doesn't exist.
Huff.h
#ifndef HuffPuff_Huff_h
#define HuffPuff_Huff_h
//---Include---
#include <iostream>
#include <vector>
#include <set>
using namespace std;
//---Node---
struct Node {
int weight;
char litteral;
string symbol;
Node* childL;
Node* childR;
void set_node(int w, char l, Node* L, Node* R){
weight = w;
litteral = l;
childL = L;
childR = R;
}
bool operator>(Node & r){
if(this->weight > r.weight)
return true;
return false;
}
};
//---Code---
struct Code {
string symbol;
char content;
};
//---HuffClass---
class Huff {
private:
typedef pair<char, int> c_pair;
vector<Code> code;
string content;
void copy_to(c_pair c);
public:
Huff(string);
~Huff();
string compress();
bool set_content();
string get_content();
string get_compress();
};
#endif
Huff.cpp
//---Include---
#include <iostream>
#include <vector>
#include "Huff.h"
#include <map>
#include <set>
using namespace std;
//---|+ -|---
Huff::Huff(string c): content(c){}
Huff::~Huff(){}
//---Compress---
struct CopyTo {
vector<Node*>* & nodes;
CopyTo(vector<Node*>* & c):nodes(c){}
void operator()(pair<char, int> c){
Node * n = new Node;
n->set_node(c.second, c.first, NULL, NULL);
nodes->push_back(n);
}
};
void show_freq(pair<char, int> p) {
cout << p.first << "\t" << p.second << endl;
}
/*void show_freq(Node* p) {
cout << p->litteral << "\t" << p->weight << endl;
}*/
string Huff::compress(){
vector<Node *>* nodes; // Vector of nodes for later use
map<char, int>* freq = new map<char, int>; // Map to find weight of nodes
for(int i = 0; i < content.length(); i++)
(*freq)[content[i]]++;
for_each(freq->begin(), freq->end(), show_freq);
CopyTo copyto(nodes); //Copy map elements to nodes in this and next one
for_each(freq->begin(), freq->end(), copyto);
delete freq;
Node p;
while(nodes->size() != 1){ //Sorts nodes by weight and then removes two of them and replaces them with one
sort(nodes->begin(), nodes->end());
vector<Node *>::iterator beg = nodes->begin();
int w= (**beg).weight + (**beg++).weight;
Node* p = new Node;
p->set_node(w, '*', *nodes->begin(), *(nodes->begin()++));
nodes->erase(nodes->begin(), nodes->begin()+2);
nodes->push_back(p);
//for_each(nodes->begin(), nodes->end(), show_freq);
cout << "--------------" << endl;
}
Node* root = *nodes->begin();
return "110";
}
Main.cpp
int main(){
Huff mike("Testing-");
mike.compress();
}
Where is including of algorithm header?
online compiler
results
Compilation output:
source.cpp: In member function 'std::string Huff::compress()':
source.cpp:76:39: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
source.cpp:94:11: warning: unused variable 'root' [-Wunused-variable]
Execution output:
- 1
T 1
e 1
g 1
i 1
n 1
s 1
t 1
I have the below struct:
struct node {
float val;
int count;
}
I have several objects of this struct. Now, I want to insert these objects into a priority queue of STL such that the priority queue orders the items by count. Any idea on how to do so? Preferably a min-heap is preferred. I know how to do the above for primitive data types, not structs
Overload the < operator:
bool operator<(const node& a, const node& b) {
return a.count > b.count;
}
I have reversed the comparison to achieve min heap without passing extra arguments to the priority queue.
Now you use it like this:
priority_queue<node> pq;
...
Edit: take a look at this post which seems to be almost exact duplicate: STL Priority Queue on custom class
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
class Boxer{
public:
string name;
int strength;
};
struct Comp{
bool operator()(const Boxer& a, const Boxer& b){
return a.strength<b.strength;
}
};
int main(){
Boxer boxer[3];
boxer[0].name="uday", boxer[0].strength=23;
boxer[1].name="manoj", boxer[1].strength=33;
boxer[2].name="rajiv", boxer[2].strength=53;
priority_queue< Boxer, vector<Boxer>, Comp> pq;
pq.push(boxer[0]);
pq.push(boxer[1]);
pq.push(boxer[2]);
Boxer b = pq.top();
cout<<b.name;
//result is Rajiv
return 0;
}
Using greater as comparison function you can use priority queue as min heap,
#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<int,vector<int>,greater<int> >pq;
pq.push(1);
pq.push(2);
pq.push(3);
while(!pq.empty())
{
int r = pq.top();
pq.pop();
cout << r << " ";
}
return 0;
}
Inserting value by changing their sign (using minus (-) for positive number and using plus (+) for negative number we can use priority queue in reversed order.
int main()
{
priority_queue<int>pq2;
pq2.push(-1); //for +1
pq2.push(-2); //for +2
pq2.push(-3); //for +3
pq2.push(4); //for -4
while(!pq2.empty())
{
int r = pq2.top();
pq2.pop();
cout << -r << " ";
}
return 0;
}
For custom data types or classes we need a to tell priority queue a way of knowing on which order it will sort our data.
struct compare
{
bool operator()(const int & a, const int & b)
{
return a>b;
}
};
int main()
{
priority_queue<int,vector<int>,compare> pq;
pq.push(1);
pq.push(2);
pq.push(3);
while(!pq.empty())
{
int r = pq.top();
pq.pop();
cout << r << " ";
}
return 0;
}
For custom structure or class you can use priority_queue in any order. Suppose, we want to sort people in descending order according to their salary and if tie then according to their age.
struct people
{
int age,salary;
};
struct compare {
bool operator()(const people & a, const people & b)
{
if(a.salary==b.salary)
{
return a.age>b.age;
} else {
return a.salary>b.salary;
}
}
};
int main()
{
priority_queue<people,vector<people>,compare> pq;
people person1,person2,person3;
person1.salary=100;
person1.age = 50;
person2.salary=80;
person2.age = 40;
person3.salary = 100;
person3.age=40;
pq.push(person1);
pq.push(person2);
pq.push(person3);
while(!pq.empty())
{
people r = pq.top();
pq.pop();
cout << r.salary << " " << r.age << endl;
}
Same result can be obtained by operator overloading :
struct people
{
int age,salary;
bool operator< (const people & p) const
{
if(salary==p.salary)
{
return age>p.age;
} else {
return salary>p.salary;
}
}
};
In main function :
priority_queue<people> pq;
people person1,person2,person3;
person1.salary=100;
person1.age = 50;
person2.salary=80;
person2.age = 40;
person3.salary = 100;
person3.age=40;
pq.push(person1);
pq.push(person2);
pq.push(person3);
while(!pq.empty())
{
people r = pq.top();
pq.pop();
cout << r.salary << " " << r.age << endl;
}
You need to provide operator< for that struct. Something like:
bool operator<(node const& x, node const& y) {
return x.count < y.count;
}
Now you can use a priority queue from the standard library.
Since C++11, you can write
auto comparer = [](const auto& a, const auto& b) {
return a.priority < b.priority;
};
std::priority_queue<Item, std::vector<Item>, decltype(comparer)> queue(comparer);
We can define user defined comparator class:
Code Snippet :
#include<bits/stdc++.h>
using namespace std;
struct man
{
string name;
int priority;
};
class comparator
{
public:
bool operator()(const man& a, const man& b)
{
return a.priority<b.priority;
}
};
int main()
{
man arr[5];
priority_queue<man, vector<man>, comparator> pq;
for(int i=0; i<3; i++)
{
cin>>arr[i].name>>arr[i].priority;
pq.push(arr[i]);
}
while (!pq.empty())
{
cout<<pq.top().name<<" "<<pq.top().priority;
pq.pop();
cout<<endl;
}
return 0;
}
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string str,int num)
{
name = str;
age = num;
}
};
// FUNCTOR
class compare
{
public:
bool operator()(Person a,Person b)
{
cout << "Comparing " << a.age << " with " << b.age << endl;
return a.age < b.age;
}
};
int main()
{
int n;
cin >> n;
priority_queue <Person, vector<Person> , compare> pq;
for(int i=1;i<=n;i++)
{
string name;
int x;
cin >> name;
cin >> x;
Person p(name,x);
pq.push(p);
}
int k = 3;
for(int i=0;i<k;i++)
{
Person p = pq.top();
pq.pop();
cout << p.name << " " << p.age << endl;
}
return 0;
}
Operator() is also commonly overloaded to implement functors or function object. For example we have a structure Person which have some default ways of searching and sorting a person by age but we want our customized ways with some other parameter like weight so we may use our own custom functor. Priority queue is one such container which accepts a functor so it knows how to sort the objects of custom data types. Each time a comparison has to be done, a object is instantiated of class compare, and it is passed two objects of person class for comparison.