Suppose we have the following problem - we want to read a set of (x, y) coordinates and a name, then sort them in order, by increasing the distance from the origin (0, 0). Here is an algorithm which use simplest bubble sort:
#include<iostream>
#include <algorithm>
using namespace std;
struct point{
float x;
float y;
char name[20];
};
float dist(point p){
return p.x*p.x+p.y*p.y;
}
void sorting(point pt[],int n){
bool doMore = true;
while (doMore) {
doMore = false; // Assume no more passes unless exchange made.
for (int i=0; i<n-1; i++) {
if (dist(pt[i]) > dist(pt[i+1])) {
// Exchange elements
point temp = pt[i]; pt[i] = pt[i+1]; pt[i+1] = temp;
doMore = true; // Exchange requires another pass.
}
}
}
}
void display(point pt[],int n){
for (int i=0;i<n;i++){
cout<<pt[i].name<< " ";
}
}
int main(){
point pts[1000];
int n=0;
while (cin>>pts[n].name>>pts[n].x>>pts[n].y){
n++;
}
sorting(pts,n);
display(pts,n);
return 0;
}
But I want to write STL sorting algorithm instead of bubble sort. How to do so?
I mean that, how should I use dist function in STL sort algorithm?
The STL sort function std::sort can take a user-defined comparison function (or function object) as an optional third argument. So if you have your items in e.g.:
vector<point> points;
You can sort them by calling:
sort(points.begin(), points.end(), my_comp);
where my_comp() is a function with the following prototype:
bool my_comp(const point &a, const point &b)
#include <algorithm>
bool sort_by_dist(point const& p1, point const& p2) {
return dist(p1) < dist(p2);
}
...
std::sort(pt, pt + n, sort_by_dist);
Related
The f() function in the class MapSquare works properly.. When I add the other class MapTriple, it is not working. f() function in the MapSquare should find the square of the elements in the vector and in the MapTriple should multiply 3 to all elements.
MapGeneric is the base class which contains the function map() which is a recursive function to access the vector elements and the f() function is a pure virtual function.
MapSquare and MapTriple are two derived classes overrides the f() function to find the square of vector elements and to multiply 3 with all the vector elements.
MapSquare works properly... but when I add MapTriple, segmentation fault occures. Please help to solve this.
#include<vector>
#include<iostream>
#include<cstdlib>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class MapGeneric
{
public:
virtual int f(int){};
vector<int> map(vector<int>, int);
};
class MapSquare:public MapGeneric
{
public: int f(int);
};
class MapTriple:public MapGeneric
{
public: int f(int);
};
class MapAbsolute:public MapGeneric
{
public: int f(int);
};
vector<int> MapGeneric::map(vector<int> v, int index)
{
if(index>=1)
{
v[index]=f(v[index]);
return map(v,index-1);
}
return v;
}
int MapSquare::f(int x)
{
return x*x;
}
int MapTriple::f(int x)
{
return 3*x;
}
int MapAbsolute::f(int x)
{
return abs(x);
}
int main()
{
//mapping square
MapSquare ob;
vector<int> L,L1,L2;
for (int i = 1; i <= 5; i++)
L.push_back(i);
L1=ob.map(L,sizeof(L));
cout<<"Square = ";
for ( vector<int>::iterator i = L1.begin(); i != L1.end(); ++i)
cout << *i<<" ";
//mapping triple
MapTriple t;
L2=t.map(L,sizeof(L));
cout<<endl<<"Triple = ";
for(vector<int>::iterator i=L2.begin();i!=L2.end();++i)
cout<<*i<<" ";
return 0;
}
A number of problems here. It looks as though you think that C++ indices start at 1, rather than zero?
if(index>=1)
{
v[index]=f(v[index]);
return map(v,index-1);
}
To me that immediately looks wrong, surely you mean:
// use size_t for indices (which cannot be negative)
vector<int> MapGeneric::map(vector<int> v, size_t index)
{
// make sure the index is valid!
if(index < v.size())
{
v[index] = f(v[index]);
return map(v, index - 1);
}
return v;
}
Secondly, the sizeof() operator does not do what you expect!! It returns the size of std::vector (which is usually 24bytes on 64 bit systems - basically 3 pointers). You should use the size() method to determine the length of the array.
// remember that indices are zero based, and not 1 based!
L1=ob.map(L, L.size() - 1);
Im trying to write a adjacency matrix representation using vectors of integer vectors , therefore vector> . However when I add members to the vector and later try and print those values nothing has changed. Most likely it has to do with "pass by value" however I have used "pass by reference" to the best of my knowledge.
Here is my header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
the cpp implementation file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix.push_back(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
for (int i=0; i< vertex_matrix.size(); i++)
{
for (int j = 0; j < vertex_matrix.size(); j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
When I use the print function I currently getting 0's.
How can I make this proper pass by reference, and have the updated values print.
Thanks
As stated in the comments, you are creating a copy of your column and then modifying the copy. What you want to do is to make a reference to it.
vector<int>& columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
Or you can access the element directly.
if (vertex_matrix[v1-1][v2-1] == INT_MAX)
{
vertex_matrix[v1-1][v2-1] = weight;
}
In print_graph you are doing the same, but here you are not modifying anything so that works, but you are making an unnecessary copy for no reason which is not ideal.
A last point is that you are calling vertex_matrix.clear() in your destructor. This is redundant, when the vector goes out of scope it will clear itself up, so you don't need to manage that.
I'm trying to implement a C++ program for Kruskal algorithm which requires me to sort the graph by weights.I'm trying using vectors(structures) but the sorting function seems to give all zeroes.How can I sort my STRUCTURE by WEIGHTS.
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
struct graph
{
int src;
int dst;
int weight;
};
bool compare(struct graph a,struct graph b)
{
return (&a.weight < &b.weight);
}
int main()
{
int ver,edges;
cin >> ver >> edges;
vector<graph> G(100);
for(int i=0; i<edges; ++i)
{
cin >> G[i].src >> G[i].dst >> G[i].weight;
}
sort(G.begin(),G.end(),compare); //trying to sort by weights
for(int i=0; i<edges; ++i)
{
cout << G[i].src << G[i].dst << G[i].weight << endl;
}
}
The & in
bool compare(struct graph a,struct graph b)
{
return (&a.weight < &b.weight);
}
takes the address, i.e. you're not comparing the weights, but their addresses. Simply omit the &, but also avoid unnecessary copies and take the graph arguments via const reference, i.e.
bool compare(graph const & a, graph const & b)
{
return a.weight < b.weight;
}
Finally, you can do this directly via a lambda as in
std::sort(G.begin(), G.end(),[](graph const&l, graph const&r)
{ return l.weight < r.weight; });
I tried solving this probblem on spoj. http://www.spoj.com/problems/BUSYMAN/
Although I was able to solve it but I got a very strange error. I tried understanding the cause of it but failed. I have two codes.
///////////////////////////////////////////////////
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class activity
{
public:
int start,end;
};
bool comp(activity p, activity q)
{
if(p.end<q.end)return true;
if(p.end==q.end&&p.start<=q.start)return true;
return false;
}
int main()
{
int t;
cin>>t;
vector<activity> v;
for(int i=0;i<t;i++)
{
int n;
cin>>n;
v.resize(n);
for(int j=0;j<n;j++)cin>>v[j].start>>v[j].end;
sort(v.begin(),v.end(),comp);
int ans=0,currend=0;
for(int j=0;j<n;j++)
{
if(v[j].start>=currend){ans++;currend=v[j].end;
}
}
cout<<ans<<endl;
}
}
/////////////////////////////////////////////
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class activity
{
public:
int start,end;
};
bool comp(activity p, activity q)
{
if(p.end<q.end)return true;
if(p.end==q.end&&p.start>=q.start)return true;
return false;
}
int main()
{
int t;
cin>>t;
int n;
vector<activity> v;
for(int i=0;i<t;i++)
{
cin>>n;
v.resize(n);
for(int j=0;j<n;j++)
cin>>v[j].start>>v[j].end;
sort(v.begin(),v.end(),comp);
int ans=0,currend=0;
for(int j=0;j<n;j++)
{
if(v[j].start>=currend)
{
ans++;currend=v[j].end;
}
}
cout<<ans<<endl;
}
}
//////////////////////////////
My problem is that the first one gives segmentation fault on spoj while second one does not. The only difference between the two is the comparison function. I just happen to define the second statement of the comparison function in two different ways which are similar. But it gives me segmentation fault in the first case but not in second case.
enter image description here
In the two images above there are two codes with respective submission ids and in the third it shows seg fault for one while not for other. You can verify with the submission ids on my spoj profile as well.
Because bool comp(activity p, activity q) doesn't meet requirements of Compare see std::sort
It should be this:
bool comp(const activity& p, const activity& q)
{
return p.end < q.end || (p.end ==q.end && p.start < q.start);
}
or
struct comp {
bool operator()(const activity& p, const activity& q) const
{
return p.end < q.end || (p.end ==q.end && p.start < q.start);
}
};
or
struct comp {
bool operator()(const activity& p, const activity& q) const
{
return std::tie(p.end, p.start) < std::tie(q.end, q.start);
}
};
The rules of C++ are that the comparator for std::sort must give a strict weak ordering.
So, the comparator must return false for equal elements. However this test:
if(p.end<q.end)return true;
if(p.end==q.end&&p.start<=q.start)return true;
return false;
returns true if the elements are equal, so this is an invalid comparator.
In your second attempt:
if(p.end<q.end)return true;
if(p.end==q.end&&p.start>=q.start)return true;
return false;
This has the same problem, also causing undefined behaviour.
You can't infer anything from the observed behaviour when the code had undefined behaviour, it is just chance (perhaps depending on some detail about your compiler's particular choice of sort algorithm) as to what behaviour you get.
Changing <= to < in the first comparator would yield a valid comparator with sort order of both end and start ascending.
I've a question to ask.
So, I have a structure call Node as shown below:
struct Node
{
int xKoor, yKoor;
Node *parent;
char nodeId;
float G;
float H;
float F;
Node(int x, int y, int id, Node * par)
{
xKoor = x;
yKoor = y;
nodeId = id;
parent = 0;
}
Node(int x, int y, char id)
{
xKoor = x;
yKoor = y;
nodeId = id;
}
};
And I have list that contains elements of this structure:
list<Node*> OPEN;
This list's size varies in time.
What I need to do is to find the Node object which has the minimum F value, then pop out that object from the list.
So, I tried to write a function as shown below:
void enKucukFliNodeBul(list<Node*> OPEN)
{
list<Node*>::iterator it = OPEN.begin();
for(it = OPEN.begin(); it != OPEN.end(); it++)
{
if(it._Ptr->_Myval->F < it._Ptr->_Next->_Myval->F)
{
}
}
}
But I'm stuck. I'm new to STL. How can I solve this?
My best regards...
You can use std::min_element with a suitable comparison function for this.
bool nodeComp(const Node* lhs, const Node* rhs) {
return lhs->F < rhs->F;
}
#include <algorithm> // for std::min_element
list<Node*>::iterator it = std::min_element(OPEN.begin(), OPEN.end(), nodeComp);
This assumes that list<Node*> is std::list<Node*>, in which case you should be aware that std::list itself is a linked list.
Other useful operations, based on your comments:
Remove a minimum value node from the list and delete it:
OPEN.erase(it);
delete *it; //
You may need to perform other operations, if your nodes depend on each other.
Sort the list:
OPEN.sort(nodeComp);
use std::min_element algirithm and overload Compare function
bool compareF(Node *lhs, Node *rhs)
{
return lhs->F < rhs->F;
}
if you are using C++03:
std::<Node*>::itertor ter = std::min_element(OPEN.begin(),OPEN.end(), compareF);
if you are using C++11:
auto iter = std::min_element(OPEN.begin(),OPEN.end(), compareF);
To sort the list, you can call OPEN.sort(compareF); to sort your list with compareF function
Try adding this:
bool compare_node_F(Node* n1, Node* n2)
{
return n1-> F< n2-> F;
}
#include <list>
#include <algorithm>
#include <cstdlib>
#include <iostream>
int main()
{
std::list<Node*> nodes;
for(int i= 100; i--;)
{
Node* n= new Node(42, 42, 42);
n-> F= i;
nodes.push_back(n);
}
std::list<Node*>::iterator min_element_iter= std::min_element(nodes.begin(), nodes.end(), compare_node_F);
std::cout<< "Min F: "<< (*min_element_iter)-> F<< '\n';
for(std::list<Node*>::iterator d= nodes.begin(); d!= nodes.end(); ++ d)
delete *d;
}