Related
using namespace boost;
typedef adjacency_list<setS, vecS, bidirectionalS,
no_property,
property<edge_weight_t, float>> Graph_type;
typedef graph_traits<Graph_type>::edge_iterator edge_iterator;
int main() {
// create graph
Graph_type g;
add_edge(0,1,g);
add_edge(1,2,g);
add_edge(2,0,g);
// output graph
std::pair<edge_iterator, edge_iterator> ei = edges(g);
for (edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter)
std::cout << source(*edge_iter, g) << " - " << target(*edge_iter, g) << "\n";
// attempt to find shortest distance from vetex 0 to all other vertices
breadth_first_search(g,0);
return 0;
}
I am attempting to call breadth_first_search, starting from vertex 0, and obtain the shortest distance to all other vertices in the graph. How am I calling the function incorrectly? And what container is recommended to store the result?
Modernizing the code first:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <iostream>
using Graph_type =
boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS,
boost::no_property,
boost::property<boost::edge_weight_t, float>>;
int main() {
// create graph
Graph_type g;
add_edge(0, 1, g);
add_edge(1, 2, g);
add_edge(2, 0, g);
// output graph
for (auto e : boost::make_iterator_range(edges(g)))
std::cout << e << "\n";
// attempt to find shortest distance from vetex 0 to all other vertices
breadth_first_search(g, 0);
}
Clang and GCC give different diagnostics, GCC's are most elaborate:
<source>: In function 'int main()':
<source>:24:32: error: no matching function for call to 'breadth_first_search(Graph_type&, int)'
24 | boost::breadth_first_search(g, 0);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
In file included from <source>:2:
/opt/compiler-explorer/libs/boost_1_78_0/boost/graph/breadth_first_search.hpp:123:6: note: candidate: 'template<class VertexListGraph, class SourceIterator, class Buffer, class BFSVisitor, class ColorMap> void boost::breadth_first_search(const VertexListGraph&, SourceIterator, SourceIterator, Buffer&, BFSVisitor, ColorMap)'
123 | void breadth_first_search(const VertexListGraph& g,
| ^~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_78_0/boost/graph/breadth_first_search.hpp:123:6: note: template argument deduction/substitution failed:
<source>:24:32: note: candidate expects 6 arguments, 2 provided
24 | boost::breadth_first_search(g, 0);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
In file included from <source>:2:
/opt/compiler-explorer/libs/boost_1_78_0/boost/graph/breadth_first_search.hpp:141:6: note: candidate: 'template<class VertexListGraph, class Buffer, class BFSVisitor, class ColorMap> void boost::breadth_first_search(const VertexListGraph&, typename boost::graph_traits<Graph>::vertex_descriptor, Buffer&, BFSVisitor, ColorMap)'
141 | void breadth_first_search(const VertexListGraph& g,
| ^~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_78_0/boost/graph/breadth_first_search.hpp:141:6: note: template argument deduction/substitution failed:
<source>:24:32: note: candidate expects 5 arguments, 2 provided
24 | boost::breadth_first_search(g, 0);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
In file included from <source>:2:
/opt/compiler-explorer/libs/boost_1_78_0/boost/graph/breadth_first_search.hpp:328:6: note: candidate: 'template<class VertexListGraph, class P, class T, class R> void boost::breadth_first_search(const VertexListGraph&, typename boost::graph_traits<Graph>::vertex_descriptor, const boost::bgl_named_params<T, Tag, Base>&)'
328 | void breadth_first_search(const VertexListGraph& g,
| ^~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_78_0/boost/graph/breadth_first_search.hpp:328:6: note: template argument deduction/substitution failed:
<source>:24:32: note: candidate expects 3 arguments, 2 provided
24 | boost::breadth_first_search(g, 0);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
Compiler returned: 1
Indeed checking the documentation shows no overload that takes 2 arguments. You need at least a third, boost::named_parameters object
Let's stick in a stub:
breadth_first_search(g, 0, boost::no_named_parameters{});
Now it should tell us which params are missing, if any: Success!
The reason you might want to pass parameters is in case your graph doesn't have implicit property maps (like vertex_index_map) for mandatory arguments, or when you want to override the default for a UTIL/OUT, like visitor. In your case it is very likely that you want to override the it because otherwise you won't be able to access the answer to your question:
std::vector<size_t> distances(num_vertices(g));
auto recorder = record_distances(distances.data(), boost::on_tree_edge{});
breadth_first_search(g, 0, visitor(make_bfs_visitor(recorder)));
for (auto v : boost::make_iterator_range(vertices(g)))
std::cout << "distance 0 .. " << v << ": " << distances.at(v) << "\n";
Prints Live On Compiler Explorer:
(0,1)
(1,2)
(2,0)
distance 0 .. 0: 0
distance 0 .. 1: 1
distance 0 .. 2: 2
BONUS/Caveats
Caution: your graph model "has" edge_weight (although your example never initializes it to non-zero values). If they are relevant, then BFS is not enough. For non-negative weights you should use Dijkstra, which happens to be a bit easier to use in my opinion:
Live
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <iostream>
using G = boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS,
boost::no_property,
boost::property<boost::edge_weight_t, float>>;
using V = G::vertex_descriptor;
int main() {
// create graph
G g;
add_edge(0, 1, 30, g);
add_edge(1, 2, 43, g);
add_edge(2, 0, 5, g);
// output graph
auto wmap = get(boost::edge_weight, g);
for (auto e : boost::make_iterator_range(edges(g)))
std::cout << e << " weight " << wmap[e] << "\n";
// attempt to find shortest distance from vetex 0 to all other vertices
auto s = vertex(0, g);
assert(s == 0);
std::vector<size_t> distances(num_vertices(g));
boost::dijkstra_shortest_paths(g, s, boost::distance_map(distances.data()));
for (auto v : boost::make_iterator_range(vertices(g)))
std::cout << "distance 0 .. " << v << ": " << distances.at(v) << "\n";
}
Prints
(0,1) weight 30
(1,2) weight 43
(2,0) weight 5
distance 0 .. 0: 0
distance 0 .. 1: 30
distance 0 .. 2: 73
FIXED:
I had the wrong declaration in the header file. After I fixed the declaration I was able to build and print it.
I am trying to print vector of lists and I get the following error when I try to build in this 3 ways. where I am wrong? Looking into other post number 2, 3 was sugested for C++11 or newer, while number 1 is classic version. ( how do i print a vector of arrays/lists using int iterator in cpp? )
I also tried using i.begin() instead of (*i).begin() for the list or vec[i].begin(), but I get other types of errors.
I am not sure which C++ version I have.
Another reference (http://www.cplusplus.com/forum/beginner/75091/).
Nothing is working.
The functions are declared in a .hpp file
[ 10%] Building CXX object CMakeFiles/a.out.gtest.dir/app/proj1.cpp.o
[ 20%] Linking CXX executable bin/a.out.gtest
/usr/bin/ld: CMakeFiles/a.out.gtest.dir/app/proj1.cpp.o: in function `phaseTwo(std::__1::vector<std::__1::list<unsigned int, std::__1::allocator<unsigned int> >, std::__1::allocator<std::__1::list<unsigned int, std::__1::allocator<unsigned int> > > >&, unsigned int)':
/home/compsci161/projects/proj1/app/proj1.cpp:43: undefined reference to `printVec(std::__1::vector<std::__1::list<unsigned int, std::__1::allocator<unsigned int> >, std::__1::allocator<std::__1::list<unsigned int, std::__1::allocator<unsigned int> > > > const&)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [CMakeFiles/a.out.gtest.dir/build.make:114: bin/a.out.gtest] Error 1
make[1]: *** [CMakeFiles/Makefile2:80: CMakeFiles/a.out.gtest.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
Here is my code. I tried different variations.
number 1
int main(){
std::vector<std::list<unsigned>> vec = {
{1, 3, 5, 55, },
{9, 20, 41, 75, },
{44, 205, 453, 567, },
{55, 245, 567, 890, },
{100, 234, 456, 678, },
};
}
void phaseTwo(std::vector<std::list<unsigned>> & vec, unsigned f)
{
printVec(vec);
}
printVec(vec);
}
void printVec(std::vector<std::list<unsigned>> vec)
{
for(std::vector<std::list<int>>::iterator i = vec.begin(); i !=vec.end(); i++)
{
for(std::list<int>::iterator iterList = (*i).begin(); iterList != (*i).end(); iterList++)
{
std::cout << *iterList << ", ";
}
std::cout << "\n ";
}
}
number 2
void printVec(std::vector<std::list<unsigned>> vec)
{
for (unsigned i = 0; i < vec.size(); i++) {
for (auto e: vec[i]) {
std::cout << e << ", ";
}
std::cout << "\n ";
}
}
number 3
void printVec(std::vector<std::list<unsigned>> vec)
{
for (auto i: vec) {
for (auto e: i) {
std::cout << e << ", ";
}
std::cout << "\n ";
}
}
You first problem:
/home/compsci161/projects/proj1/app/proj1.cpp:43: undefined reference to `printVec(std::__1::vector<std::__1::list<unsigned int, std::__1::allocator<unsigned int> >, std::__1::allocator<std::__1::list<unsigned int, std::__1::allocator<unsigned int> > > > const&)'
The important big undefined reference to printVec.
Is because at the point where you call the function the compiler has not seen a declaration that such a function exists.
{100, 234, 456, 678, },
};
printVec(vec); // At this point.
// This is the first time the compiler has seen
// the function: printVec
}
Solve this be forward declaring the function. OR move the main() to the bottomo of the program so it is written after the printVec() function.
Another Issue:
You are passing std::vector<std::list<unsigned>> to the function.
But if you look closely you are getting an iterator for:
std::vector<std::list<int>> // Notice int is not unsigned.
Here:
for(std::vector<std::list<int>>::iterator i
^^^^^^^^
// and
for(std::list<int>::iterator
^^^^^^^
Why not use version 3. It is designed to solve this exact problem.
Other ways are to use type alias to represent the types. That way if you change the type in one place it automatically changes in all places that it is used.
using ListOfData = std::list<unsigned>;
using VectorOfDataList = std::vector<ListOfData>;
void printVec(VectorOfDataList vec) {
// STUFF
}
Now if you change the type of the underlying data from unsigned to int you only change it in one place and all locations (that use VectorOfDataList will automatically be changed to use the new underlying type.
A basic "Code Smell" is caused by needing to touch the code in multiple places because of one change. You should be able to change the thing in preferably one place and this change will affect all usage points.
An issue with your loop.
You are always using values (thus causing copies to be made).
void printVec(std::vector<std::list<unsigned>> vec)
{
for (auto i: vec) {
// ^^^^^ here i is a value.
// i.e. not a reference. So you are making
// a copy of the list into i.
for (auto e: i) {
std::cout << e << ", ";
}
std::cout << "\n ";
}
}
I would write like this:
void printVec(std::vector<std::list<unsigned>> vec)
{
for (auto const& i: vec) { // Notice the const&
for (auto const& e: i) { // Notice the const& (not strictly required
// but makes using the for loop consistent.
std::cout << e << ", ";
}
std::cout << "\n ";
}
}
As a side note.
You realize you are passing the vector by value. As such a copy is made of the whole vector (and all contained list).
// Pass by value.
void printVec(std::vector<std::list<unsigned>> vec)
// Pass by const reference.
void printVec(std::vector<std::list<unsigned>> const& vec)
// Because it is a reference the compiler does not need to make a copy.
Update: The issue may be in the betweenness code. If I comment out the call to brandes_betweenness_centrality the code will compile. the problem may not be the index set up as previously thought. I'll award bounty if you can come up with an alternative call to brandes_betweenness_centrality that will allow keeping the index external.
I'm trying to convert some of my old vecS code to work with listS, specifically the brandes_betweenness_centrality algorithm.
I'm trying to keep the Vertex and Edge properties very light weight and work mainly with external properties. The reason for this is that I don't know what all I'll want to associate with them at this point.
The errors I'm getting are coming from inside adjacency_list.hpp so I figure the problem is with our old friend vertex_index_t with listS.
The following code shows how to reproduce the compile error. In this working example, you can change the definition to stuff a vertex_index into the graph definition and change the set up in the betweenness method for completely working code (which runs betweenness correctly).
The complete example:
#include <iostream>
#include <algorithm>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/betweenness_centrality.hpp>
#include <boost/timer.hpp>
using namespace std;
enum edge_t {A,B};
struct VertexProperties{
std::string id;
};
struct EdgeProperties{
edge_t type;
};
//vertex_index in as internal property, switch to this graph and change below vertex map for working code
//typedef boost::adjacency_list < boost::listS, boost::listS, boost::undirectedS,
// boost::property<boost::vertex_index_t,size_t,VertexProperties>, EdgeProperties > DynamicNet;
// No internal vertex_index
typedef boost::adjacency_list < boost::listS, boost::listS, boost::undirectedS,
VertexProperties, EdgeProperties > DynamicNet;
typedef boost::graph_traits<DynamicNet>::vertex_descriptor DynamicNetVertex;
typedef boost::graph_traits<DynamicNet>::vertex_iterator DynamicNetVI;
typedef boost::graph_traits<DynamicNet>::edge_descriptor DynamicNetEdge;
typedef boost::graph_traits<DynamicNet>::edge_iterator DynamicNetEI;
void calcBetweenness(DynamicNet &g,
std::vector<double> &v_centrality_vec,
std::vector<double> &e_centrality_vec);
int main(int argc, char* argv[]){
cout << "betweenness" << endl;
DynamicNet net;
//Fig. 1, wheen graph (a - h), modified with added z added to a
//http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/betweenness_centrality.html
DynamicNetVertex a = boost::add_vertex(net); net[a].id = "a";
DynamicNetVertex b = boost::add_vertex(net); net[b].id = "b";
DynamicNetVertex c = boost::add_vertex(net); net[c].id = "c";
DynamicNetVertex d = boost::add_vertex(net); net[d].id = "d";
DynamicNetVertex e = boost::add_vertex(net); net[e].id = "e";
DynamicNetVertex f = boost::add_vertex(net); net[f].id = "f";
DynamicNetVertex g = boost::add_vertex(net); net[g].id = "g";
//core
DynamicNetVertex h = boost::add_vertex(net); net[h].id = "h";
boost::add_edge(a,h,net);
boost::add_edge(b,h,net);
boost::add_edge(c,h,net);
boost::add_edge(d,h,net);
boost::add_edge(e,h,net);
boost::add_edge(f,h,net);
boost::add_edge(g,h,net);
//add an edge to make the calculation more interesting
DynamicNetVertex z = boost::add_vertex(net); net[z].id = "z";
boost::add_edge(a,z,net);
vector<double> v_centrality_vec(boost::num_vertices(net),0.0);
vector<double> e_centrality_vec(boost::num_edges(net),0.0);
boost::timer t;
t.restart();
calcBetweenness(net,v_centrality_vec,e_centrality_vec);
double s = t.elapsed();
cout << s << " s" << endl;
cout << endl;
cout << "Vertex betweenness" << endl;
DynamicNetVI vi,ve;
size_t i = 0;
for(boost::tie(vi,ve) = boost::vertices(net); vi != ve; ++vi){
cout << net[*vi].id << "\t" << v_centrality_vec.at(i) << endl;
++i;
}
cout << endl;
cout << "Edge betweenness" << endl;
DynamicNetEI ei,ee;
i = 0;
for(boost::tie(ei,ee) = boost::edges(net); ei != ee; ++ei){
DynamicNetEdge e = *ei;
cout << net[boost::source(e,net)].id << "\t"
<< net[boost::target(e,net)].id << "\t" << e_centrality_vec.at(i) << endl;
++i;
}
cin.get();
}
void calcBetweenness(DynamicNet &g,
std::vector<double> &v_centrality_vec,
std::vector<double> &e_centrality_vec)
{
std::cout << "betweenness called" << std::endl;
//vertex
//Uncomment and change to internal vertex graph above for working code.
/*
typedef std::map<DynamicNetVertex,size_t> StdVertexIndexMap;
StdVertexIndexMap viMap;
typedef boost::property_map<DynamicNet, boost::vertex_index_t>::type VertexIndexMap;
VertexIndexMap v_index = boost::get(boost::vertex_index,g);
DynamicNetVI vi,ve;
size_t i = 0;
for(boost::tie(vi,ve) = boost::vertices(g); vi != ve; ++vi){
boost::put(v_index,*vi,i);
++i;
}
boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMap >
v_centrality_map(v_centrality_vec.begin(), v_index);
*/
//this code which exactly mimics the working approached used by edge results in an error
typedef std::map<DynamicNetVertex,size_t> StdVertexIndexMap;
StdVertexIndexMap viMap;
typedef boost::associative_property_map<StdVertexIndexMap> VertexIndexMap;
VertexIndexMap v_index(viMap);
DynamicNetVI vi,ve;
size_t i = 0;
for(boost::tie(vi,ve) = boost::vertices(g); vi != ve; ++vi){
boost::put(v_index,*vi,i);
++i;
}
boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMap >
v_centrality_map(v_centrality_vec.begin(), v_index);
//edge, this appraoch works fine for edge
typedef std::map<DynamicNetEdge,size_t> StdEdgeIndexMap;
StdEdgeIndexMap eiMap;
typedef boost::associative_property_map<StdEdgeIndexMap> EdgeIndexMap;
EdgeIndexMap e_index(eiMap);
DynamicNetEI ei,ee;
i = 0;
for(boost::tie(ei,ee) = boost::edges(g); ei != ee; ++ei){
boost::put(e_index,*ei,i);
++i;
}
boost::iterator_property_map< std::vector< double >::iterator, EdgeIndexMap >
e_centrality_map(e_centrality_vec.begin(), e_index);
brandes_betweenness_centrality(g,v_centrality_map, e_centrality_map);
}
The error:
Error 1 error C2182: 'reference' : illegal use of type 'void' ... \boost_1_58_0\boost\graph\detail\adjacency_list.hpp 2543
Error 2 error C2182: 'const_reference' : illegal use of type 'void' ... \boost_1_58_0\boost\graph\detail\adjacency_list.hpp 2544
MSVS output:
1>------ Build started: Project: testBetweenness, Configuration: Release
Win32 ------
1>Compiling...
1>testBetweenness.cpp
1>...\boost_1_58_0\boost/graph/detail/adjacency_list.hpp(2543) : error C2182: 'reference' : illegal use of type 'void'
1> ...\boost_1_58_0\boost/graph/detail/adjacency_list.hpp(2619) : see reference to class template instantiation 'boost::adj_list_any_vertex_pa::bind_<Tag,Graph,Property>' being compiled
1> with
1> [
1> Tag=boost::vertex_index_t,
1> Graph=boost::adjacency_list<boost::listS,boost::listS,boost::undirectedS,pintk::VertexProperties,pintk::EdgeProperties>,
1> Property=pintk::VertexProperties
1> ]
1> ...\boost_1_58_0\boost/graph/detail/adjacency_list.hpp(2752) : see reference to class template instantiation 'boost::detail::adj_list_choose_vertex_pa<Tag,Graph,Property>' being compiled
1> with
1> [
1> Tag=boost::vertex_index_t,
1> Graph=boost::adjacency_list<boost::listS,boost::listS,boost::undirectedS,pintk::VertexProperties,pintk::EdgeProperties>,
1> Property=pintk::VertexProperties
1> ]
1> ...\boost_1_58_0\boost/graph/properties.hpp(208) : see reference to class template instantiation 'boost::adj_list_vertex_property_selector::bind_<Graph,Property,Tag>' being compiled
1> with
1> [
1> Graph=boost::adjacency_list<boost::listS,boost::listS,boost::undirectedS,pintk::VertexProperties,pintk::EdgeProperties>,
1> Property=pintk::VertexProperties,
1> Tag=boost::vertex_index_t
1> ]
1> ...\boost_1_58_0\boost/graph/properties.hpp(217) : see reference to class template instantiation 'boost::detail::vertex_property_map<Graph,PropertyTag>' being compiled
1> with
1> [
1> Graph=boost::adjacency_list<boost::listS,boost::listS,boost::undirectedS,pintk::VertexProperties,pintk::EdgeProperties>,
1> PropertyTag=boost::vertex_index_t
1> ]
1> ...\boost_1_58_0\boost/graph/betweenness_centrality.hpp(562) : see reference to class template instantiation 'boost::property_map<Graph,Property,Enable>' being compiled
1> with
1> [
1> Graph=boost::adjacency_list<boost::listS,boost::listS,boost::undirectedS,pintk::VertexProperties,pintk::EdgeProperties>,
1> Property=boost::vertex_index_t,
1> Enable=void
1> ]
1> ...\Visual Studio 2008\Projects\yapnl\yapnl\ProteinNetworks.h(82) : see reference to function template instantiation 'void boost::brandes_betweenness_centrality<pintk::DynamicNet,boost::iterator_property_map<RandomAccessIterator,IndexMap>,boost::iterator_property_map<RandomAccessIterator,EdgeIndexMap>>(const Graph &,CentralityMap,EdgeCentralityMap,boost::graph::detail::no_parameter)' being compiled
1> with
1> [
1> RandomAccessIterator=std::_Vector_iterator<double,std::allocator<double>>,
1> IndexMap=VertexIndexMap,
1> Graph=pintk::DynamicNet,
1> CentralityMap=boost::iterator_property_map<std::_Vector_iterator<double,std::allocator<double>>,VertexIndexMap>,
1> EdgeCentralityMap=boost::iterator_property_map<std::_Vector_iterator<double,std::allocator<double>>,EdgeIndexMap>
1> ]
1>...\boost_1_58_0\boost/graph/detail/adjacency_list.hpp(2544) : error C2182: 'const_reference' : illegal use of type 'void'
1>Build log was saved at "file://...\Visual Studio 2008\Projects\yapnl\testBetweenness\Release\BuildLog.htm"
1>testBetweenness - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
This answer, helped me add boost::vertex_index_t property in the graph definition which allowed the code to run by using boost::property<boost::vertex_index_t,size_t,VertexProperties>.
I would like a way to keep vertex_index_t completely external from the graph and add it just before I run the algorithm.
The virtually identical code for setting up edge_index allows this. Am I missing something or is this an MSVS thing or could it be a bug?
My specific question is: What do I need to change to keep vertex_index out of the graph definition, add it on the fly, and still run the algorithm?
As I stated in the update, it looks like the problem was in betweenness centrality. Digging through the dispatches in the source, and looking at the parameters in the docs I found that if vertex_index_map is not passed to the algorithm it defaults to get(vertex_index, g) which as we know does not exist in this particular graph.
After some time wrapping my head around named bgl_named_params, I figured out I could pass the v_index variable as a named parameter.
The following code did the trick:
brandes_betweenness_centrality(g,
boost::centrality_map(v_centrality_map).edge_centrality_map(e_centrality_map).vertex_index_map(v_index));
I think the error was in the brandes_betweenness_centrality trying to call get(vertex_index,g)and failing on the listS graph.
This question already has answers here:
Standard library sort and user defined types
(3 answers)
Closed 7 years ago.
Sorry for posting a duplicate post but I have my best to find the answer around still couldnt solve the error. I follow many example but it just doesnt seem to work. I having problem with sorting a vector of object.
Its giving me a whole chunk of error on that line of code with sort which i cant even debug.
When i comment out that line it running fine without error.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
//some other codes
vector<PointTwoD> Point;
bool sortByCiv(PointTwoD &d1, PointTwoD &d2) {
return d1.getCivIndex() < d2.getCivIndex();
}
void print_top5()
{
int num = 0;;
cout << "Total no. of records available = " << Point.size() << endl;
cout << "Prining top 5 explorations destinations..." << endl;
**sort(Point.begin(), Point.end(), sortByCiv);**
for (int i = 0; i < 5; i++)
{
num++;
int x, y;
float civ;
x = Point[i].getX();
y = Point[i].getY();
civ = Point[i].getCivIndex();
if (civ > 0){
cout<< num << " Civ Index :" << civ << " at sector (" << x << ", " << y << ")" << endl;
} else {
cout<< num << " <no other records available>" << endl;
}
}
}
I am able to print out the results nicely in the for loop, i just need it to be in descending order. Thanks a lot.
this is the error message
In file included from /usr/include/c++/4.8/algorithm:62:0,
from MissionPlan.cpp:6:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<PointTwoD*, std::vector<PointTwoD> >; _Tp = PointTwoD; _Compare = bool (*)(PointTwoD&, PointTwoD&)]’:
/usr/include/c++/4.8/bits/stl_algo.h:2296:78: required from ‘_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<PointTwoD*, std::vector<PointTwoD> >; _Compare = bool (*)(PointTwoD&, PointTwoD&)]’
/usr/include/c++/4.8/bits/stl_algo.h:2337:62: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<PointTwoD*, std::vector<PointTwoD> >; _Size = long int; _Compare = bool (*)(PointTwoD&, PointTwoD&)]’
/usr/include/c++/4.8/bits/stl_algo.h:5490:44: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<PointTwoD*, std::vector<PointTwoD> >; _Compare = bool (*)(PointTwoD&, PointTwoD&)]’
MissionPlan.cpp:33:44: required from here
/usr/include/c++/4.8/bits/stl_algo.h:2263:35: error: invalid initialization of reference of type ‘PointTwoD&’ from expression of type ‘const PointTwoD’
while (__comp(*__first, __pivot))
^
/usr/include/c++/4.8/bits/stl_algo.h:2266:34: error: invalid initialization of reference of type ‘PointTwoD&’ from expression of type ‘const PointTwoD’
while (__comp(__pivot, *__last))
First things first - this is not a minimum compilable example. If you could publish something we can compile (say here : http://www.tutorialspoint.com/compile_cpp11_online.php) it would help a lot.
Having said that, your comparison function should take arguments by const reference. In addition, in order to sort in descending order you'd need to change the logic of the predicate as follows:
bool sortByCiv(const PointTwoD &d1, const PointTwoD &d2) {
return d1.getCivIndex() > d2.getCivIndex();
}
edit:
Have a look at this link - this code compiles and you can use it as a reference.
http://goo.gl/kUVP5r
What I wanted to do is generate n numbers of nearly sorted value.
For example, user will enter nvalue of 1000.
It will then pass the sorting job by calling the partial sorting function.
Basically, I will just sort half of the total values.
Meaning to say, out of 1000 that has been generated..only first half or 500 values will be sorted only.
After done sorting, it shall push all the nearly sorted value into a vector.
However, I was facing some errors which I can't understand what does it mean during compilation. Can anyone help me on these? Thank you
2 following errors:
1)'partial_sort' : ambiguous call to overloaded function c:\users\mk\documents\visual studio 2013\projects\algorithm analysis\algorithm analysis\nearlysorted.cpp 49 1 Algorithm Analysis
2)IntelliSense: more than one instance of overloaded function "partial_sort" matches the argument list:
function template "void partial_sort(rand_access begin, rand_access sort, rand_access end)"
function template "void std::partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last)"
argument types are: (std::_Vector_iterator>>, std::_Vector_iterator>>, std::_Vector_iterator>>) c:\Users\Mk\Documents\Visual Studio 2013\Projects\Algorithm Analysis\Algorithm Analysis\nearlysorted.cpp 49 2 Algorithm Analysis
Code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
template <class rand_access>//class
void partial_sort(
rand_access begin,
rand_access sort,
rand_access end
);
template <class rand_access, class BinaryPred>//overloading
void partial_sort(
rand_access begin,
rand_access sort,
rand_access end,
BinaryPred comp
);
//Function prototype
//void decrease_store(int val, vector<int> &aVec); TODO SOON
void nearlystd_store(int val, vector<int> &aVec);
int main()
{
int nvalue;
vector<int> int_vector;
cout << "How many numbers would you like to generate?\n";
cin >> nvalue;//get input from user
nearlystd_store(nvalue, int_vector);// pass user input to the function
system("pause");
return 0;
}
void nearlystd_store(int val, vector<int> &aVec)//nearly sorted function
{
vector<int>::iterator Iter;// a vector
int num;
for (int i = 0; i < val; i ++)//generate from the start till desired nvalue
{
aVec.push_back(val - i);//push into this vector
}
partial_sort(aVec.begin(), aVec.begin() + (val / 2), aVec.end());//sort half in the vector
cout << "The Output:\n";
for (Iter = aVec.begin(); Iter != aVec.end(); ++Iter)//push sorted value
{
cout << *Iter << " " << endl;//aVec.push_back(int()); --- Not sure if correct
}
}
EDITTED CODE:
Thanks to both llya & Chris for helping out
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//Function prototype
//void decrease_store(int val, vector<int> &aVec); TODO SOON
void nearlystd_store(int val, vector<int> &aVec);
int main()
{
int nvalue;
vector<int> int_vector;
cout << "How many numbers would you like to generate?\n";
cin >> nvalue;//get input from user
nearlystd_store(nvalue, int_vector);// pass user input to the function
system("pause");
return 0;
}
void nearlystd_store(int val, vector<int> &aVec)//nearly sorted function
{
vector<int>::iterator Iter;// a vector
for (int i = 0; i < val; i ++)//generate from the start till desired nvalue
{
aVec.push_back(val - i);//push into this vector
}
partial_sort(aVec.begin(), aVec.begin() + (val / 2), aVec.end());//sort half in the vector
cout << "The Output:\n";
for (Iter = aVec.begin(); Iter != aVec.end(); ++Iter)//push sorted value
{
cout << *Iter << " " << endl;//aVec.push_back(int()); --- Not sure if correct
}
}
Let's see compilation errors (next time add it in a question!):
prog.cpp: In function ‘void nearlystd_store(int, std::vector<int>&)’:
prog.cpp:49:68: error: call of overloaded ‘partial_sort(std::vector<int>::iterator, __gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::vector<int>::iterator)’ is ambiguous
partial_sort(aVec.begin(), aVec.begin() + (val / 2), aVec.end());//sort half in the vector
^
prog.cpp:49:68: note: candidates are:
prog.cpp:8:6: note: void partial_sort(rand_access, rand_access, rand_access) [with rand_access = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]
void partial_sort(
^
In file included from /usr/include/c++/4.8/algorithm:62:0,
from prog.cpp:3:
/usr/include/c++/4.8/bits/stl_algo.h:5308:5: note: void std::partial_sort(_RAIter, _RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]
partial_sort(_RandomAccessIterator __first,
^
Here compiler informs your, that it is hard to decide, which implementation of partial_sort must be called. There are two possible options, so compiler can't be sure, which one is right. You need to avoid such uncertainty. In this case you can rename wrong declaration (i.e. remove all lines from 'template //class' to '//Function prototype').
prog.cpp:43:9: warning: unused variable ‘num’ [-Wunused-variable]
int num;
^
And this is just warning. Here you declared variable num, but never use it. It is better to remove such lines from a code to simplify it.