I'm trying to convert this function to use a vector object instead of an integer array.
The vector object looks like this:
std::vector<Heltal *> htal;
The Heltal class contains a private integer named heltal.
How would I sort the htal vector using the function below?
void Array::Sort(int a[], int first, int last)
{
int low = first;
int high = last;
int x = a[(first+last)/2];
do {
while(a[low] < x) {
low++;
}
while(a[high] > x) {
high--;
}
if(low<=high) {
std::swap(a[low],a[high]);
low++;
high--;
}
} while(low <= high);
if(first < high)
Array::Sort(a,first,high);
if(low < last)
Array::Sort(a,low,last);
}
The correct solution is to ditch your custom sort and use std::sort from <algorithm>. This will pretty much be guaranteed to be faster and more optimal in almost every case. Then you just have:
#include <algorithm>
...
std::vector<Heltal *> htal;
...
// sort by pointer value
std::sort(htal.begin(), htal.end());
If you want to sort by object value rather than pointer value, either use std::vector<Heltal> instead of std::vector<Heltal *> (which is almost certainly what you should be doing anyway), or pass a comparison function to std::sort.
Example using C++11 lambda for this:
std::sort(htal.begin(), htal.end(), [](Heltal *a, Heltal *b) { return *a < *b; });
Related
I'm trying to make quicksort program. I just couldn't understand why and how this error is coming. I've tried every method online but I'm unable to catch the issue. If I'm doing this with array in place of vector, I'm getting correct output but with vector error is coming.
My errors are:
.\quicksort.cpp:7:28: error: cannot convert 'std::vector<double>' to 'double' in initialization
double pivot = values[end];
.\quicksort.cpp:10:19: error: no match for 'operator<=' (operand types are 'std::vector<double>' and 'double')
if (values[i] <= pivot) {
How to convert the vector<double> to double then?
Here's my code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int partition(vector<double> *values, int start, int end) {
double pivot = values[end];
int pIndex = start;
for (int i=start; i<end; i++) {
if (values[i] <= pivot) {
swap(values[i], values[pIndex]);
pIndex++;
}
}
swap(values[pIndex], values[end]);
return pIndex;
}
void quicksort(vector<double> *values, int start, int end) {
if (start<end) {
int pIndex;
pIndex = partition(values, start, end);
quicksort(values, start, pIndex-1);
quicksort(values, pIndex+1, end);
}
}
int main() {
int n;
cin >> n;
vector<double> values(n);
for (int i = 0; i < n; i++) {
cin >> values[i];
}
quicksort(values, 0, n-1);
for (int j=0; j<n; j++) {
cout<<values[j]<<" ";
}
return 0;
}
How to rectify these errors?
References not pointers
int partition(vector<double>& values, int start, int end) {
void quicksort(vector<double>& values, int start, int end) {
If you used a pointer (but you shouldn't) the correct code would be
double pivot = (*values)[end];
Pointers are not the same as the things they are pointing to, you have to use * or -> to get at the object that a pointer points to. You don't have to do this with references.
You have a C++ compiler so use it, send Reference to your object instead of pointer:
void quicksort(vector<double> &values, const int start, const int end);
int partition(vector<double> &values, const int start, const int end)
And your compile time error gone, with pointer to the object you need to call your function like this:
quicksort(&values, 0, n - 1);
Because you need it's address (actually your pointer need it).
And you need to use operator[] of std::vector which is first need to get std::vector object from pointer to it:
double pivot = (*values)[end];
As you see it's ugly and could be complex, So it's better to use References instead of pointer in those situations.
Your partition and quicksort functions take pointers as parameters not reference values.
Your functions should be declared as such:
int partition(vector<double> &values, int start, int end)
void quicksort(vector<double> &values, int start, int end)
The reason you are getting the error is that since the values parameter is a pointer when you use the array accessor ([i]) it assumes that values is an array of vectors and returns a vector not a double.
you should pass vector<double>& to your function instead of vector<double>*, i.e. pass by reference instead of pass by pointer. If passing by pointer, then you need to access the elements of the vector with ->[index].
I am trying to make a generic selection sort function using templates.
What I have made is:
template<typename T>
void nrsort(T &a,int size)
{
// Applying Selection Sort
double temp; // This is the issue
for (int i = 0; i < size ; i++)
{
double minimum=a[i]; // This one too
for (int j = i+1; j < size ; j++)
{
if(a[j]<minimum)
{
temp=a[i];;
a[i]=a[j];
minimum=a[j];
a[j]=temp;
}
}
}
}
I want a generic template that may be able to sort integers, floating point numbers, characters, etc.
This above mentioned code works but the major problem is that I have hardcoded the double temp; and double minimum and conversion of data takes place everytime.
If I write my main method as follows:
int main()
{
int values[]={4,3,6,1};
nrsort(values,4);
for (int i = 0; i < 4 ; i++)
{
cout<<values[i]<<"\t";
}
return 0;
}
Then the type T deduced in the template is int [4] an array of four integers. Inside the function, all these are converted to double and the code works fine.
But my question is, Is there any way so that I don't have to hardcode it to double and use something like the generic type `T'.
Thanks.
Your function isn't as generic as it could be. The STL-way to solve such a problem is to use iterators. It will allow you to sort C-style arrays, std::vectors and anything else that provides a random access iterator. Your function should take a pair of iterators like this:
template <typename IteratorT>
void
my_sort(IteratorT begin, IteratorT end);
Then, if you #include <iterator>, you can query the value type (ie what you get if you dereference a IteratorT) like so
using ValueT = typename std::iterator_traits<IteratorT>::value_type;
Now, ValueT is a type alias for your type.
You can provide a convenience wrapper function if you like:
#include <utility> // for std::begin() and std::end()
template<typename ContainerT>
void
my_sort(ContainerT& container)
{
using std::begin;
using std::end;
my_sort(begin(container), end(container));
}
There is one problem: These function templates will match all too eagerly, even if the iterators are not random access iterators. You can use SFINAE trickery to enable your template only if std::iterator_traits<IteratorT>::iterator_category is std::random_access_iterator_tag. Or you could provide an overload that copies the elements (or pointers / iterators to them) into a std::vector, sorts that, and then copies the elements back. Sometimes, this is the best you can do.
If you fix the scope of temp, you can simply use auto:
template<typename T>
void nrsort(T &a,int size)
{
// Applying Selection Sort
for (int i = 0; i < size ; i++)
{
auto minimum=a[i]; // This one too
for (int j = i+1; j < size ; j++)
{
if(a[j]<minimum)
{
auto temp=a[i];;
a[i]=a[j];
minimum=a[j];
a[j]=temp;
}
}
}
}
It will automatically deduce the right type.
Imagine the following scenario:
class A
{
int a[50];
int* GetAPtr() { return a; };
};
...
A b;
if(b.GetAPtr()[22] == SOME_RANDOM_DEFINE) do_this_and_that();
Is this kind of access considered bad practice? b.GetAPtr()[22]
To clarify my situation:
1. I cannot use new/malloc in this case, the array muste be static
2. This is meant to encapsulate older C code that uses multiple arrays where this comes extremly handy
3. I know that returning a pointer can possibly return a NULL pointer, we do not talk about that issue here
If you really need such const expression you could make it into a function:
class A
{
int a[50];
bool check_this_and_that() { return a[22] == SOME_RANDOM_DEFINE; };
};
...
A b;
if(b.check_this_and_that()) do_this_and_that();
magic numbers are bad in general but inside a class logic it's more forgiveable and outsiders don't have to see this.
Yes, it is bad practice, because you have no way of knowing how long the array is. You could follow the idiomatic standard library approach and return begin and end pointers, pointing to the first and one-past-last elements.
class A
{
int a[50];
int* begin() { return &a[0]; };
int* end() { return &a[50]; };
const int* begin() const { return &a[0]; };
const int* end() const { return &a[50]; };
size_t size() const { return 50; } // this could be handy too
};
As well as giving you the tools to iterate over the elements like you would over a standard library container, this allows you to check whether any pointer to an element of the array is < v.end(). For example
it* it = b.begin() + 22;
if(it < b.end() && *it == SOME_RANDOM_DEFINE) do_this_and_that();
This makes it trivial to use standard library algorithms:
A b;
// fill with increasing numbers
std::iota(b.begin(), b.end());
// sort in descending order
std::sort(s.begin(), s.end(), std::greater<int>());
// C++11 range based for loop
for (auto i : b)
std::cout << i << " ";
std::endl;
GetAPtr is a method for accessing a private data member. Now ask yourself what are the advantages of b.GetAPtr()[22] over b.a[22]?
Encapsulating data is a good way to maintain constraints on and between data members. In your case there is at least a correlation between the a array and its length 50.
Depending on the use of A you could build a interface providing different access patterns:
class A {
int a[50];
public:
// low level
int atA(unsigned i) const { return a[i]; }
// or "mid" level
int getA(unsigned i) const { if(i >= 50) throw OutOfRange(); return a[i]; };
// or high level
bool checkSomething() const { return a[22] == SOME_RANDOM_DEFINE; }
};
This is my code for Dijkstra's algorithm:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#define pp pair<int,int>
using namespace std;
struct pri
{
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
int main()
{
priority_queue<pp,vector<pp>,pri> q;
int n;
cin>>n;
vector<pp> g[n+1];
int e,u,v,w,i;
cin>>e;
for(i=0;i<e;i++)
{
cin>>u>>v>>w;
g[u].push_back(pp(v,w));
g[v].push_back(pp(u,w));
}
int s;
cin>>s;
int d[n+1];
for(i=1;i<=n;i++)
d[i]=999;
d[s]=0;
q.push(pp(s,d[s]));
while(!q.empty())
{
u=q.top().first;
q.pop();
int size=g[u].size();
for(int i=0;i<size;i++)
{
v=g[u][i].first;
w=g[u][i].second;
cout<<u<<" "<<" "<<w<<endl;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
q.push(pp(v,d[v]));
}
}
}
for(i=1;i<=n;i++)
printf("node %d,min weight=%d\n",i,d[i]);
return 0;
}
In this I can't understand the working of
priority_queue<pp,vector<pp>,pri> q;
That is related to:
struct pri
{
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
What is the use of () operator in this? I mean how it functions in this code?
Also why are we using & in operator()?
Also, how does this comparator work in priority queue definition?
And why are we using constant in operator definition?
i mean to say how is exactly this comparison in operator working and cant we use any
other symbol as = * # or any other instead of ()
I think the compare function you write is wrong.
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
which the correct one should be
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second>p2.second;
}
Because in priority_quequeyou can find that The expression comp(a,b), where comp is an object of this type and a and b are elements in the container, shall return true if a is considered to go before b in the strict weak ordering the function defines.
Because in the Dijkstra algorithm, the node with smaller value should has higher priority, thus the operator we used here should be
p1.second>p2.second
(By using your code to solve a problem, it took me a long time to figure out this problem that my program's results were always different with the correct one.)
(By the way, in the Dijkstra algorithm itself, I think once a node was pop as the smallest one, there is no need to pop it again and update all the nodes that connected to it. This could save a lot of time.)
struct pri {
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
Creates a function object by overloading () operator
This is passed to the priority_queue as the compare class
& is used to pass the pair as constant reference, making sure that no copying of actual arguments take place, (by passing them as reference), at same time the function can't modify their values (by using const keyword)
With the use of this function object, the queue determines how to insert the values (pair).
In this case the second value of pair is used for comparison.
When declaring variables (including function arguments), the & is to mark the variable as a reference. It's very basic and common thing to use references for some types of arguments, partly because it passes the arguments without creating copies (so good for e.g. a std::vector) and it also allows non-const references to be changed in the function as a form of output argument.
As for the use of operator() in a structure like this, it makes instances of the structure function objects, in other words, objects that can be invoked like a function.
I think your question is about the line priority_queue<pp,vector<pp>,pri> q;?
This declares a variable q of type priority_queue<pp,vector<pp>,pri>. priority_queue is defined as
template<class T,
class Container = vector<T>,
class Compare = less<typename Container::value_type> >
class priority_queue;
So, pp is the type of the elements, vector<pp> is the container (the same as the default), and pri is a function object which is used to compare items in the queue (Compare). The priority_queue uses Compare to order its elements. If the elements cannot be compared directly, or the default is not appropriate, then you can supply your own. In this case, the elements will be order by second member in each element pair.
Basically the same as the other answers, just a little more detail -- the operator() code is what defines how the priority queue should do comparisons to determine item priority in the queue. Using this type of framework, you can have a priority queue defined to store any type of objects, and the priority queue can be ordered according to any kind of custom ordering you want on the objects.
I refactored this code and checked it with hackerrank.
#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
#include <vector>
#include <deque>
#include <set>
#include <limits>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;
struct pri
{
typedef pair<int,int> pp;
typedef deque<pri::pp > list;
typedef vector< pri::list > graph;
int operator() (pp&p1,const pp&p2)
{
return p1.second>p2.second;
}
typedef priority_queue< pri::pp, pri::list, pri > queue;
};
static int f1(const int x){ return x==std::numeric_limits<int>().max()?-1:x; }
int main()
{
int t;
cin>>t;
while(t--){
int n,e;
cin>>n>>e;
pri::graph g(n+1);
for(int i(0);i<e;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(pri::pp(v,w));
g[v].push_back(pri::pp(u,w));
}
vector<int> d(n+1,std::numeric_limits<int>().max());
int s; cin>>s;
d[s]=0;
pri::queue q;
q.push(pri::pp(s,d[s]));
set<int> vs;
while(!q.empty()) {
const int u(q.top().first);
const pri::list& gu(g[u]);
q.pop();
vs.insert(u);
for( pri::list::const_iterator i(gu.begin()); i != gu.end(); ++i ) {
const int v(i->first), w(i->second);
if( vs.find(v)==vs.end() ){
// cout<<u<<" "<<v<<" "<<w<<endl;
if( d[v]>d[u]+w ) {
d[v]=d[u]+w;
q.push(pri::pp(v,d[v]));
}
}
}
}
copy_if(d.begin()+1,d.end(),d.begin(),std::bind2nd(std::not_equal_to<int>(),0));
transform(d.begin(),d.end()-2,ostream_iterator<int>(cout," "),f1);
cout<<endl;
}
return 0;
}
I'd like to use sort() to do the following
I have a text char[] T which is (private) member of a class. The text has length n.
I also ave an array int[] P that contains the first n integers.
I'd like to std::sort P such that the lexicographic order among suffixes of T are preserved
i.e., for any i < j we have that T[P[i]...n] is lex smaller than T[P[j]...n].
I'm able to do it when char[] T is a global variable by defining
bool myfunction (int i,int j) {
int m = i, l = j;
while(m<n and l <n) {
if(T[m] != T[l]) return (T[m]<T[l]);
m++; l++;
}
return (m<l);
}
and calling std::sort(P, P+n, myfuction)
I'm in truble when T is a member of an object (and sort is called by a method of that object).
How can I define myfunction so that T is visible?
Should it be member of that object? If yes, how?
Thank you very much.
Edit: bool instead of int
As you guessed, one way to do it is by defining yourfunction() as a public member of that class.
Example:
#include <algorithm>
#include <vector>
using namespace std;
class T
{
private:
int value;
public:
T()
{
value = rand() % 100;
}
static bool Compare(const T &a, const T &b)
{
return a.value < b.value;
}
};
int main(int argc, char** argv)
{
vector<T> data;
//add some data
for (int i=0; i<10; i++)
data.push_back(T());
//sort using static method that can access private attributes
std::sort(data.begin(), data.end(), T::Compare);
}
If sort represents std::sort, the function that you are using as predicate is wrong for a couple of reasons, the first of which is that the returned type from the function should be a bool and not an int.
The next thing that is wrong is that the predicate is required to be consistent, that is, given two inputs a and b the result of predicate( a, b ) must be either true or false and always the same. If that condition is not met, the result of calling sort will be undefined, possibly including an infinite loop.
The approach (rather than the predicate itself) is probably not good either, as the number of times that the predicate will be called depends on the input data, and the results of the different calls to the predicate (until the algorithm thinks, that according to your partial order, the sequence is sorted).
You probably need a functor object:
struct myfunctor {
const char *T;
size_t n;
myfunctor(const char *T, size_t n) : T(T), n(n) {}
bool operator()(int i, int j) {
// stuff using T and n
}
// Optionally, something along these lines, I haven't tested it
template <size_t N> myfunctor(const char (&x)[N]) : T(&x[0]), n(N) {}
template <size_t N> myfunctor(char (&x)[N]) : T(&x[0]), n(N) {}
};
SomeObjectContainingT x;
std::sort(P, P+n, myfunctor(x.T, x.n));
Or if x.T is an actual array rather than just a pointer, the template constructors will capture the array size from the type, no need for a second parameter:
std::sort(P, P+n, myfunctor(x.T));
Edit: sorry, missed that T is private. I think you have two issues here, scope and accessibility. The functor solves the scope problem, now for the accessibility.
If you want external functions to access T, x must provide a means to access it. For example, it could return the functor object:
class SomeObjectContaining T {
char T[23];
public:
myfunctor comparator() { return myfunctor(T); }
};
std::sort(P, P+n, x.comparator());
Or you could mess about with friend: define your functor class as a friend of SomeObjectContainingT, then pass the object to its constructor rather than the array.