C++ sort long deque - c++

I'm trying to sort first half of a deque deque<data> sortDValues of pairs
struct data {
int dValue;
int index;
};
by the dValue using c++ function with lambda expression
sort(sortDValues.begin(), sortDValues.begin() + partASize - i,
[](data const &a, data const &b) { return a.dValue > b.dValue; });
This approach works well most of time, but in some special cases the final program falls. I've located, that the problem of this is in the sort function, however, I couldn't figure out, why.
I'm not sure, if it can have anything in common with filling this dequeue
deque<data> sortDValues;
for(number n : indices)
{
if(perm[n] >= partASize)
sortDValues.push_back(dValues[n]);
else
sortDValues.push_front(dValues[n]);
}
I can give a specific case of this problem: first number is the index, the second the dValue:
Thank you in advance for answers, I wasn't able to find out, where the problem is.

Related

Checking whether an element is in a C++ set is really slow

I'm implementing an algorithm that implies a lot of checking whether elements are in a set/list. I was using std::vector containers but time was increasing exponentially as the vector would grow.
I've decided I would try using std::set containers in order not to have to explore the entire container to know whether it contains a certain element.
I implemented the following function that checks whether an element is part of a given set:
bool in_set(set<Node> node_set){
return node_set.find(*this) != node_set.end();
}
However, that function is taking around 2s for very small sets (1-3 elements) which makes my entire algorithm unusable.
The custom class I'm using look like this:
class Node{
public:
int d;
int h_score;
int coordinates [3];
Node* parent_address;
};
The comparison operator that I implemented look like this:
bool operator<(Node other) const{
return concatenate(concatenate(this->coordinates[0], this->coordinates[1]), this->coordinates[2]) <
concatenate(concatenate(other.coordinates[0], other.coordinates[1]), other.coordinates[2]);
}
Edit: The concatenate function does not seem to take a lot of time while executing, it looks like this:
int concatenate(int i, int j) {
int result = 0;
for (int x = i; x <= j; x++) {
result = result * 10 + x;
}
return result;
}
Do you know why it is taking so much time, and more importantly, how to make it faster?
First of all, you can try to pass Set as const & and not in operator< also as const &.
bool in_set(const set<Node>& node_set){
return node_set.find(*this) != node_set.end();
}
And
bool operator<(const Node& other) const
It will use ref instead of a copy of your set and Node objects.
Do you know why it is taking so much time
concatenate(1, 100000000) takes 1.3 second on my raspberry pi, that way to do is too slow, and in fact useless
Note also that because of the possible overflows concatenate can give the same result for different nodes, this is non compatible for an operator<
how to make it faster?
you have to find something else than these calls of concatenate to implement your operator<
What is your need ? is the order in the set is important or it can be replaced by any one else ?
It is not mandatory to create a unique identifier to compare two nodes, compare them directly, for instance :
bool operator<(const Node & other) const{
if (coordinates[0] < other.coordinates[0])
return true;
if (coordinates[0] >= other.coordinates[0])
return false;
if (coordinates[1] < other.coordinates[1])
return true;
if (coordinates[1] >= other.coordinates[1])
return false;
return (coordinates[2] < other.coordinates[2]);
}
To understand that operator< works you can consider node.coordinates supports a big number having 3 times the size of an int, so I compare the higher bits, then if equals the medium bits, then if equals the lower bitsused for a set
Your operator< takes a copy of the Node. There's also no need to create strings to compare, the built-in tuple class can do that:
How about:
bool operator<(const Node& other) const {
return std::make_tuple(coordinates[0], coordinates[1], coordinates[2]) <
std::make_tuple(other.coordinates[0], other.coordinates[1], other.coordinates[2]);
}

Recursive Permutation, Ellis Horowitz Algorithms and data structure Confusion.

I am a beginner programmer in my first year of university. My tutor has asked us to do some research on a recursive algorithm and make it none recursive. No natter how much I try it seems impossible.
The question reads
A is a character string (e.g. A = "hello") and interchange, which is
an abstraction, exchanges the k-th with the i-th character of A,
e.g. CALL interchange("hello", 2, 3) would change "hello" to
"hlelo").
The idea is to print out all the possible permutations
The version in c++ reads
void perm(char*a, const int k, const int n)
{
if(k==n)
{
cout << a;
}
else
{
for (i=k;i<=n;i++)
{
interchange(a, k, i);
perm(a, k+1, n)
}
}
}
My tutor much prefers to use a language called ADL that seems only to appear in the Horowitz book "algorithms and data structures". He has posed the question in ADL so I will add that code in too, its very easy to understand.
proc perm(IN a, IN k, IN n)
if k=n then
print(a)
else
{
for i <- k to n do
call interchange(a,k,i)
call perm( a, k+1, n)
end
}
end
thanks for anyone who can help.
Martyn
A recursive algorithm is simply an algorithm that uses a stack.
The recursion allows you to use the call stack as your data stack.
Any recursive function taking this form:
void perm(char*a, const int k, const int n)
{
// check if your code should return
// make a recursive call with new data
}
Can be changed to this:
void perm(char*a, const int k, const int n)
{
// Create a stack, push (a,k,n)
while ( /* stack isn't empty */ )
{
// check if stack should be *popped* (instead of returning)
// Put new data on the stack (instead of recursing)
}
}
Here's a hint, without doing your homework for you. As you walk down the string, looking at the ith character, you're in one of three possible states:
i == k
i == n
else
What do you print in each of those three cases?

Compare two static arrays

I have an issue how to implement to compare two static arrays, ie.
string bufferNames[]={"apple","orange","banana","pomegranate","pear"};
string bufferPictures[] = {"apple.bmp","orange.bmp","banana.bmp","pomegranate.bmp","pear.bmp"};
Each item in the bufferNames presents the choice that to someone has been given, when the picture from the bufferPictures has been loaded onto the screen. So, if I for example get orange.bmp using rand() function that iterates through that list, how can I get the same one corresponding element orange and two other random not correct elements. Any help would be appreciated.
Thanks in advance.
P.S. If further breaking in of the problem is needed, just say it so.
This should do it. The code makes use of the C++11 features. You will
need to adapt it, to pass it off as homework.
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
struct Picture {
std::string name, file;
bool operator==(const Picture& x) const { return this->name == x.name && this->file == x.file; }
bool operator!=(const Picture& x) const { return !(*this == x); }
};
int main()
{
std::vector< Picture > pics =
{
{"apple", "apple.bmp"},
{"orange", "orange.bmp"},
{"banana", "banana.bmp"},
{"pear", "pear.bmp"},
};
// determined by random choice
const Picture& choice = pics[0];
std::vector< Picture > woChoice;
std::copy_if(pics.begin(), pics.end(), std::back_inserter(woChoice),
[&choice](const Picture& x) {
return x != choice;
});
// random shuffle the remainder and pick the first
// two. alternatively and for more efficience use std::random to
// generate indices
std::random_shuffle(woChoice.begin(), woChoice.end());
std::cout << woChoice[0].name << std::endl;
std::cout << woChoice[1].name << std::endl;
return 0;
}
So, if I for example get orange.bmp using rand() function that iterates through that list, how can I get the same one corresponding element orange and two other random not correct elements.
If you use rand() to get a number (let's call it x) between 0 and 4 inclusive (based on there being 5 distinct values in the arrays), then you can use that number in both arrays to find the related word and image.
To get one other random incorrect element, you can call rand() in a loop until you get a value other than x. Let's call it y.
To get another random incorrect elements, you can call rand() in a loop until you get a value other than x and y.
There are other ways to do this, but that's probably easiest to understand and implement.
The names in arrays correspond to each other. So, if you need fruit
number i, take bufferNames[i] and bufferPictures[i] in parallel way.
Ensure that names ARE parallel. Simply making the second array
elements from the first array elements.
As for random in range 0..n-1 excluding elements number i,j (j>i), count it so:
temp=random(n-3);
k=(temp>=i?temp+1:temp);
k=(k>=j?k+1:k);
And again, take bufferNames[k] and bufferPictures[k].
It is not simple, it is VERY simple.

quicksort debug

Can anyone point out why this implementation of quick sort is not working, i have gone through it several times and can't seem to find the error
int quickPartition ( int data[], int p, int r)
{
int x=data[r];
int i=p-1;
for (int j=p; j<r; j++)
{
if(data[j]<x)
{
i++;
int temp=data[i];
data[i]=data[j];
data[j]=temp;
}
int temp=data[i+1];
data[i+1]=data[r];
data[r]=temp;
}
i++;
cout<<"i:"<<i<<endl;
return i;
}
void myQuickSort(int data[], int left, int right)
{
if(left<right)
{
int q=quickPartition(data,left,right);
myQuickSort(data,left,q-1);
myQuickSort(data,q+1,right);
}
}
the call to quicksort is simply
myQuickSort(anArray,0,size-1);
Methinks
int temp=data[i+1];
data[i+1]=data[r];
data[r]=temp;
should go outside the for loop.
Your implementation of partition looks entirely bogus. What you want is iterate from both ends and on each end find an object which belongs to the opposite part. If the iterators meet, you are done. Otherwise you swap the two objects and find the next pair.
Personally, I can't think properly in the abstractions you are using: I have a much easier time to think in terms of iterators pointing to the respective objects and finding the next object to swap should be functions as well. Also, I need to factor things into small, comprehensible bits. You swap objects at some point. This should be a separate function. With this partition() would look something like this:
int* partition(int* left, int* right, int value) {
while (left != right)
{
left = find_forward(left, right, value);
right = find_backward(left, right, value);
if (left != right)
{
swap(left, right);
}
}
return left;
}
I haven't tested this but something along those lines should work. Obviously, I would just use std::swap() to swap elements and std::find_if() to find suitable locations (for the backward case using std::reverse_iterator). Well, if this weren't a homework assignment you would just use std::sort() anyway: it doesn't use a vanilla quick-sort but a variation which detects that it is running into a bad case and uses std::heap_sort() in this case to guarantee that it stays O(n log n).

Please help - sorting integers in structs

I have a struct like this:
struct db {
string name,sur;
int num;
};
And declared an array of db structs:
struct db a[10];
and every member of a[] is filled with a name, surname and a number but there can be the same number appearing multiple times.
I need to sort the numbers, and print the results, i.e. sort by the num of each struct and the print the name, sur and the num in each line starting from the smallest num going down to the largest. I don't know how to do this, please help me.
First, in C++ you don't need to repeat "struct" every time.
You can use the std::sort() function and give it a custom predicate.
bool db_cmp(const db &left, const db &right)
{
return left.num < right.num;
}
//...
db a[10];
std::sort(a, a + 10, db_cmp);
// then, display the contents of a..
You can use qsort.
int db_comparator ( const void * elem1, const void * elem2 )
{
struct db *first = (struct db *) elem1, *second = (struct db *) elem2;
return first->num - second->num;
}
qsort(a, sizeof(a)/sizeof(a[0]), sizeof(a[0]), db_comparator);
Do you have to implement your own sorting algorithm?
If so I strongly suggest typing "Sorting Algorithms" into google and/or checking out the wikipedia page.
Bubble sort is REALLY easy to implement (But is a poor sorting algorithm). It will come down to checking each number against each other and then swapping them is one is less than the other. String sorting is easy too as strcmp returns you a value less than 0 for a string "less" than the one being compared to and greater than zero for one "greater" than.
If you don't need to implement your own algorithm then use std::sort.
You could add a comparison method to your structure:
struct db
{
string name;
string sur;
int num;
bool operator <(const db& other)
{
if (name == other.name)
{
return sur < other.sur;
}
return name < other.name;
};
Now you can use the std::sort algorithm because your object has the '<' operator defined.