How to return structure array in C++ - c++

So I've been trying to implement Kruskal's algorithm, first I want to make clear the question is not related to the implementation of the algorithm. I've created one graph.hpp file, one kruskalsAlgo.hpp and main.cpp as follows respectively:
#pragma once
struct Edge
{
int source;
int destination;
int weight;
};
struct Graph
{
int V;
int E;
Edge* edge;
};
Graph* create_graph(int V, int E)
{
Graph* graph = new Graph;
graph -> V = V;
graph -> E = E;
graph -> edge = new Edge[E];
return graph;
}
#include <stdlib.h>
#include <tuple>
#include "../Graph/Graph.hpp"
class Kruskals_Algo
{
private:
struct subset
{
int parent;
int rank;
};
void make_set(subset*, int);
int find_set(subset*, int);
void _union(subset*, int, int);
public:
Edge* kruskal(Graph*);
void print_kruskals_MST(Edge*, int);
};
void Kruskals_Algo::make_set(subset* subsets, int V)
{
subsets[V].parent = V;
subsets[V].rank = 0;
}
int Kruskals_Algo::find_set(subset* subsets, int V)
{
if(subsets[V].parent != V)
subsets[V].parent = find_set(subsets, subsets[V].parent);
return subsets[V].parent;
}
void Kruskals_Algo::_union(subset* subsets, int x, int y)
{
int xroot = find_set(subsets, x);
int yroot = find_set(subsets, y);
if(subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if(subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
inline int myComp(const void* a, const void* b)
{
Edge* a1 = (Edge*)a;
Edge* b1 = (Edge*)b;
return a1 -> weight > b1 -> weight;
}
Edge* Kruskals_Algo::kruskal(Graph* graph)
{
int V = graph -> V;
Edge result[V];
Edge* result_ptr = result;
int e = 0;
int i = 0;
qsort(graph -> edge, graph -> E, sizeof(graph -> edge[0]), myComp);
subset* subsets = new subset[(V * sizeof(subset))];
for (int v = 0; v < V; ++v)
make_set(subsets, v);
while(e < V - 1 && i < graph -> E)
{
Edge next_edge = graph -> edge[i++];
int x = find_set(subsets, next_edge.source);
int y = find_set(subsets, next_edge.destination);
if (x != y)
{
result[e++] = next_edge;
_union(subsets, x, y);
}
}
//return std::make_tuple(res, e);
return result_ptr;
}
void Kruskals_Algo::print_kruskals_MST(Edge* r, int e)
{
int minimumCost = 0;
for(int i=0; i<e; ++i)
{
std::cout << r[i].source << " -- "
<< r[i].destination << " == "
<< r[i].weight << std::endl;
minimumCost = minimumCost + r[i].weight;
}
std::cout << "Minimum Cost Spanning Tree: " << minimumCost << std::endl;
}
#include <iostream>
#include "Graph/Graph.hpp"
#include "Kruskals_Algo/kruskalsAlgo.hpp"
//#include "Prims_Algo/primsAlgo.hpp"
using namespace std;
class GreedyAlgos
{
public:
void kruskals_mst();
//void prims_mst();
};
void GreedyAlgos::kruskals_mst()
{
Kruskals_Algo kr;
int V;
int E;
int source, destination, weight;
cout << "\nEnter the number of vertices: ";
cin >> V;
cout << "\nEnter the number of edges: ";
cin >> E;
Edge* res;
Graph* graph = create_graph(V, E);
for(int i=0; i<E; i++)
{
cout << "\nEnter source, destinstion and weight: ";
cin >> source >> destination >> weight;
graph -> edge[i].source = source;
graph -> edge[i].destination = destination;
graph -> edge[i].weight = weight;
}
//std::tie(result, E) = kr.kruskal(graph);
res = kr.kruskal(graph);
kr.print_kruskals_MST(res, E);
}
int main()
{
int choice;
GreedyAlgos greedy;
greedy.kruskals_mst();
return 0;
}
So my question here is when I debug the program the values in Edge result[V], which is a structure array, are calculated correctly, at position [0] [1] [2] as in the following picture:
but when the function print_kruskals_MST(res, E) is called from the main the values printed are different:
Is there any pointer thing that I'm doing wrong?
Thanks in advance!
P.S. Ignore the comments!

This answer might not answer your question directly but it should shed some light on the problem.
First of all, yes you have a lot of pointer problems...
Secondly, pair ANY use of the new operator with the delete operator. As it stands, you have a bunch of memory leaks.
Also, why create_graph? Create a constructor for Graph instead (and a destructor since the class has an Edge* edge it needs to take care of).
struct Graph
{
int V;
int E;
Edge* edge;
// constructor
Graph(int V, int E)
{
this->V = V;
this->E = E;
this->edge = new Edge[E];
}
// destructor
~Graph()
{
// nullify the member variable before deleting its memory is just a safety measure pertaining to multithreading.
Edge* _edge = this->edge;
this->edge = nullptr;
delete _edge;
}
};
Then change Graph* graph = create_graph(V, E); into Graph* graph = new Graph(V, E); and do delete graph when you're done using it.
Make sure you remove all memory leaks and we can go on to discussing referencing the correct data (f.ex. by me changing my answer).

Related

C++ exception thrown

I am learning C++ and have lost quite some time trying to solve to understand the reason of the error i am getting.
When i run the code below i am getting an Exception thrown. It happens when the program ends, so i believe it's related to the Edge pointer:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct Edge {
int src, dest;
};
class Graph {
public:
int V, E;
Edge *edge = new Edge[E * sizeof(Edge)];
Graph(int Ver, int Edg);
};
Graph::Graph(int Ver, int Edg) {
V = Ver;
E = Edg;
}
Graph* createGraph(int V, int E) {
Graph* graph = new Graph(V,E);
return graph;
}
int find(int* parents, int val) {
if (parents[val] == -1)
return val;
return find(parents, parents[val]);
}
void Union(int *parents, int x, int y) {
parents[x] = y;
}
int isCycle(Graph* graph) {
int* parents = new int[graph->V * sizeof(int)];
memset(parents, -1, graph->V * sizeof(int));
for (int i = 0; i < graph->E; i++) {
int x = find(parents, graph->edge[i].src);
int y = find(parents, graph->edge[i].dest);
if (x == y) {
return 1;
};
Union(parents, x, y);
}
return 0;
}
int main()
{
int V = 9, E = 8;
Graph* graph = createGraph(V, E);
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[6].src = 0;
graph->edge[6].dest = 6;
graph->edge[5].src = 0;
graph->edge[5].dest = 7;
graph->edge[1].src = 1;
graph->edge[1].dest = 2;
graph->edge[2].src = 3;
graph->edge[2].dest = 2;
graph->edge[3].src = 4;
graph->edge[3].dest = 3;
graph->edge[4].src = 4;
graph->edge[4].dest = 5;
graph->edge[7].src = 5;
graph->edge[7].dest = 7;
if (isCycle(graph))
cout << "graph contains cycle";
else
cout << "graph doesn't contain cycle";
return 0;
}
I started learning C++ only few months ago, can somebody help me to understand why I am getting that exception?
Edge *edge = new Edge[E * sizeof(Edge)];
Unless E is initialized, this multiplies an uninitalized variable by sizeof(Edge) (which is also wrong on its face value as well, but we'll get to it later). This is undefined behavior.
Graph::Graph(int Ver, int Edg) {
V = Ver;
E = Edg;
}
This isn't good enough. The default values of class members, if specified, are used to initialize them before the constructor's body starts running.
The proper way to do this is to use the constructor's initialization section:
Graph::Graph(int Ver, int Edg) : V{Ver}, E{Ver}
{
}
This initializes V and E first, so now:
Edge *edge = new Edge[E * sizeof(Edge)];
So here, E is now initialized, fixing this problem. But this is still slightly incorrect. It's clear, based on the rest of the code, that this should really be:
Edge *edge = new Edge[E];
In C++, when you wish to declare an array of, say, 4 integers, all you have to do is declare:
int n[4];
The compiler takes care of multiplying 4 by however many bytes it takes to hold an int. The same thing is true for the new statement. If your goal is to construct an array of #E Edges, that would be, unsurprisingly: new Edge[E]. This same mistake occurs several times in the shown code.

C++ Graph class pointers confusion

I'm trying to build a graph class where the graph is represented by adjacency lists. The graph itself is a vector of pointers where each pointer points to a linked list of nodes. For whatever reason, when I use the print graph function the program outputs nothing. Can anyone show me what I am doing wrong and perhaps where my misunderstanding of pointers is? Thanks in advance!
#include <array>
#include <vector>
#include <tuple>
#include <unordered_map>
class Node
{
public:
int vertex;
int value;
Node* next;
Node(int ver)
{
vertex = ver;
};
};
class Graph
{
public:
int n_nodes;
std::unordered_map<int,Node*> graph;
Graph(int n)
{
n_nodes = n;
for(int i=0;i<n;i++)
{
graph.insert({i,nullptr});
};
};
void add_edge(int src,int des,int val)
{
Node node_des = Node(des);
node_des.value = val;
node_des.next = graph[src];
graph[src] = &node_des;
Node node_src = Node(src);
node_src.value = val;
node_src.next = graph[des];
graph[des] = &node_src;
};
void print_graph()
{
for(int i =0; i<n_nodes;i++)
{
std::string str = "Head "+std::to_string(i);
Node node = *graph[i];
while (&node != nullptr)
{
str=str+" -> "+std::to_string(node.vertex);
node = *(node.next);
};
std::cout<<str<<std::endl;
};
};
};
int main()
{
Graph g = Graph(6);
g.add_edge(0,1,3);
g.add_edge(2,1,4);
g.add_edge(0,4,1);
g.add_edge(4,5,6);
g.add_edge(5,3,2);
g.add_edge(4,3,3);
g.add_edge(3,2,5);
g.add_edge(4,1,1);
g.add_edge(3,1,2);
g.print_graph();
return 0;
}```
If it´s possible, you may just use vector of vector instead of linked lists and not use pointers at all. Because memory cache some insertions in vectors operations may be faster than linked lists, a structure like :
struct Node2 {
int vertex;
int value;
};
struct Edge2 {
int src, des, value;
};
struct Graph2 {
int n_nodes;
std::vector<std::vector<Node2>> graph;
void add_edge(Edge2 edge) {
graph[edge.src].emplace_back(edge.des, edge.value);
graph[edge.des].emplace_back(edge.src, edge.value);
}
void add_edge(std::initializer_list<Edge2> edges)
{
std::for_each(edges.begin(), edges.end(), [this](auto &e) { add_edge(e); });
};
}
Endup bening easier and faster than linked lists;
https://quick-bench.com/q/cmX2-2IYA873TR4qn5aV4ijjUQo
Made these changes thanks to #drescherjm. The issue was that I had created a local variable and referenced its address instead of explicitly creating a pointer and setting it to a new node instance where the object's lifetime is dynamically controlled.
#include <bits/stdc++.h>
#include <array>
#include <vector>
#include <tuple>
#include <unordered_map>
class Node
{
public:
int vertex;
int value;
Node* next;
Node(int ver)
{
vertex = ver;
};
};
class Graph
{
public:
int n_nodes;
std::unordered_map<int,Node*> graph;
Graph(int n)
{
n_nodes = n;
for(int i=0;i<n;i++)
{
graph.insert({i,nullptr});
};
};
void add_edge(int src,int des,int val)
{
Node * node_des = new Node(des);
node_des->value = val;
node_des->next = graph[src];
graph[src] = node_des;
Node * node_src = new Node(src);
node_src->value = val;
node_src->next = graph[des];
graph[des] = node_src;
};
void print_graph()
{
for(int i =0; i<n_nodes;i++)
{
std::string str = "Head "+std::to_string(i);
Node * node_ptr = graph[i];
while (node_ptr != nullptr)
{
str=str+" -> "+std::to_string(node_ptr->vertex);
node_ptr = node_ptr->next;
};
std::cout<<str<<std::endl;
};
};
};
int main()
{
Graph g = Graph(6);
g.add_edge(0,1,3);
g.add_edge(2,1,4);
g.add_edge(0,4,1);
g.add_edge(4,5,6);
g.add_edge(5,3,2);
g.add_edge(4,3,3);
g.add_edge(3,2,5);
g.add_edge(4,1,1);
g.add_edge(3,1,2);
g.print_graph();
return 0;
}

Kruskal's Algorith

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;
}

free(): invalid pointer error on vector.push_back()

My code gives me free(): invalid pointer error (I don't call free, so my understanding is that it has something to do with how vectors operate internally). I am beginner to C++, so though I checked other answers to similar questions, I fail to see what exactly causes the issue.
I have a grid graph (i.e. vertex is connected with its 4-neighbors). Some vertices hold a special value, which is written done in a file in a form:
row columns value
The code:
graph::graph(const char *file_name) {
ifstream infile(file_name);
istringstream iss;
int R = 2; // number of rows
int C = 4; // number of columns
for (int i=0; i<R*C; i++) add_vertex(i+1);
adj = new std::vector<edge*>[R*C]; // adjacency list
// add all edges to the grid
for (int r=0; r<R; r++) {
for (int c=0; c<C; c++) {
if (c!=C-1) add_edge(vertices[r*C+c], vertices[r*C+(c+1)]);
if (r!=R-1) add_edge(vertices[r*C+c], vertices[(r+1)*C+c]);
}
}
int P = 2; // number of vertices holding a special value
for (int i=0; i<P; i++) {
getline(infile, line);
iss.str(line);
iss >> r >> c >> p;
vertices[r*C+c]->set_value(p);
p_vertices.push_back(vertices[r*C+c]);
iss.clear();
}
void graph::add_vertex(int v) {
auto *vert = new vertex(v);
vertices.push_back(vert);
}
void graph::add_edge(vertex *v, vertex *u) {
edge e = std::make_tuple(v, u, 1);
adj[v->get_id()].push_back(&e);
adj[u->get_id()].push_back(&e);
}
Header:
#include "vertex.h"
typedef std::tuple<vertex*, vertex*, int> edge;
class graph {
private:
std::vector<vertex*> vertices; // all vertices
std::vector<vertex*> p_vertices; // vertices with a special value
std::vector<edge*> *adj; // adjacency list
public:
explicit graph(const char *file_name);
void add_vertex(int v);
void add_edge(vertex *v, vertex *u);
};
Header for a vertex:
#include <string>
#include <vector>
class vertex {
private:
int id;
int val;
public:
explicit vertex(int id) {
this->id = id;
this->val = 0;
};
int get_id() { return id; };
void set_value(int p) { val = p; };
};
Example input:
0 0 1
1 2 3
The error disappears if I comment out this line:
p_vertices.push_back(vertices[r*C+c]);
And remains even if I try to change p_vertices to std::vector<int> instead of std::vector<vertex*> (and use p_vertices.push_back(r*C+c)).
Thanks for any hints on how to fix the error.

Priority queue for user-defined types

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.