While trying to make this merge-sort algorithm with recursive calls, i ended up getting an exception of std::out_of_range.
I don't know much about debugging and finding causes of errors. Below i will post the code(not full, only some parts) and a sourcefile containing the same code(full version, of course).
I will gladly listen to suggestions, even if they don't provide any help against this error, so feel free to comment this code and make jokes of me :)
https://docs.google.com/file/d/0ByVN9ccAyFY2dkVLN0ZlTWVHZG8/edit
Main func
int main()
{
vector<int> original; //input vector
input (&original); //write input to vector<int> original
divide(&original); //pass the vector
for(unsigned int i=0;i<original.size();i++)//output the results
cout<<original.at(i);
}
Input func
int input(vector<int> *inVec) //read all input until non-integer
{
int tmp;
while (cin>>tmp)
inVec->push_back(tmp);
for(unsigned int i=0;i<inVec->size();i++)
cout<<inVec->at(i)<<endl;
}
Divide
int divide(vector<int> *original)
{
int origL=original->size();
if(origL>1)
{
vector<int> first; //vectors for holding 2 halfs of "original"
vector<int> second; //
first.assign(original->begin(),original->begin()+origL/2);//1st half of "original"
second.assign(original->begin()+origL/2+1,original->end());//2nd half
divide(&first); //recursive call until "first" and
divide(&second); //"second" include only one number
merge(&first,&second,original);//merge first and second back into one vector
}
}
Merge func
int merge(vector<int> *A,vector<int> *B,vector<int> *original)
{
//clear the original vector. we will use it to store sorted results.
original->erase(original->begin(),original->end());
unsigned int i=0,j=0;
//out the smallest number from A and B into
//original[0] and so on. This makes it a
//sorting algorithm.
for(i=0;i<A->size();i++)
{
if(j<B->size())
if(A->at(i)<=B->at(j))
original->push_back(A->at(i));
else{
original->push_back(B->at(j));
i--;j++;}
}
//the ABOVE loop scans whole vector A or B.
//if there are still uncopied elements in
//the other vector, then we check for them and
//push them into original.
if(j<B->size())
for(i=j;i<B->size();i++)
original->push_back(B->at(i));
if(i<A->size())
for(j=i;j<A->size();j++)
original->push_back(A->at(j));
return EXIT_SUCCESS;
}
EDIT1:
Made the changes to MERGE, so now there are no runtime errors. However, output is not right. If someone notices what could cause the problem, please kindly tell me. Meanwhile I am going to try to find it myself.
What will happen when you run out of elements in B in the function merge? OOR. Try a test case when all the elements in B are smaller than the ones in A and only call merge to see what I mean.
Also this is c++ please use reference in preference to pointers.
There exists a bug in your merge function, you should test if either vector B or vector A is empty, or the access to the vectors will cause the exception.
Next part is incorrect:
first.assign(original->begin(),original->begin()+origL/2);
second.assign(original->begin()+origL/2+1,original->end());
F.e. when you have origL==2, first vector will be { original[0] }, and second vector will be empty. You must reimplement filler for second vector:
second.assign(original->begin()+origL/2,original->end())
Related
Here is my function code fragment that checks whether two arrays have distinctly common elements and returns a new vector with those elements. However there is a run time error, I do not see it and cannot fix it. I learned how to use the unique function from here:
Checking for duplicates in a vector
vector<int> distinctCommonElements(vector<int>&x, vector<int>&y)
{
vector<int>z;
for(vector<int>::iterator itx=x.begin(); itx<x.end(); itx++)
{
int ctr=0;
int memory=0;
for(vector<int>::iterator ity=y.begin(); ity<=y.end(); ity++)
{
if(*itx==*ity&&ctr==0)
{
ctr++;
z.push_back(*itx);
}
}
}
//inspiration from stack overflow and the c++ reference for unique algorithm
sort(z.begin(),z.end()); //sort due to the implementation of the unique algorithm
z.erase(unique(z.begin(),z.end()), z.end()); //unique checks adjacent elements, hence sort first,
//hence answer always sorted
return z;
}
I have 2 structs, one simply has 2 values:
struct combo {
int output;
int input;
};
And another that sorts the input element based on the index of the output element:
struct organize {
bool operator()(combo const &a, combo const &b)
{
return a.input < b.input;
}
};
Using this:
sort(myVector.begin(), myVector.end(), organize());
What I'm trying to do with this, is iterate through the input varlable, and check if each element is equal to another input 'in'.
If it is equal, I want to insert the value at the same index it was found to be equal at for input, but from output into another temp vector.
I originally went with a more simple solution (when I wasn't using a structs and simply had 2 vectors, one input and one output) and had this in a function called copy:
for(int i = 0; i < input.size(); ++i){
if(input == in){
temp.push_back(output[i]);
}
}
Now this code did work exactly how I needed it, the only issue is it is simply too slow. It can handle 10 integer inputs, or 100 inputs but around 1000 it begins to slow down taking an extra 5 seconds or so, then at 10,000 it takes minutes, and you can forget about 100,000 or 1,000,000+ inputs.
So, I asked how to speed it up on here (just the function iterator) and somebody suggested sorting the input vector which I did, implemented their suggestion of using upper/lower bound, changing my iterator to this:
std::vector<int>::iterator it = input.begin();
auto lowerIt = std::lower_bound(input.begin(), input.end(), in);
auto upperIt = std::upper_bound(input.begin(), input.end(), in);
for (auto it = lowerIt; it != upperIt; ++it)
{
temp.push_back(output[it - input.begin()]);
}
And it worked, it made it much faster, I still would like it to be able to handle 1,000,000+ inputs in seconds but I'm not sure how to do that yet.
I then realized that I can't have the input vector sorted, what if the inputs are something like:
input.push_back(10);
input.push_back(-1);
output.push_back(1);
output.push_back(2);
Well then we have 10 in input corresponding to 1 in output, and -1 corresponding to 2. Obviously 10 doesn't come before -1 so sorting it smallest to largest doesn't really work here.
So I found a way to sort the input based on the output. So no matter how you organize input, the indexes match each other based on what order they were added.
My issue is, I have no clue how to iterate through just input with the same upper/lower bound iterator above. I can't seem to call upon just the input variable of myVector, I've tried something like:
std::vector<combo>::iterator it = myVector.input.begin();
But I get an error saying there is no member 'input'.
How can I iterate through just input so I can apply the upper/lower bound iterator to this new way with the structs?
Also I explained everything so everyone could get the best idea of what I have and what I'm trying to do, also maybe somebody could point me in a completely different direction that is fast enough to handle those millions of inputs. Keep in mind I'd prefer to stick with vectors because not doing so would involve me changing 2 other files to work with things that aren't vectors or lists.
Thank you!
I think that if you sort it in smallest to largest (x is an integer after all) that you should be able to use std::adjacent_find to find duplicates in the array, and process them properly. For the performance issues, you might consider using reserve to preallocate space for your large vector, so that your push back operations don't have to reallocate memory as often.
It's kinda like a search for something. And to make the code clearer to read i wrote the function a recursive one. But problem is when the target is being reached i want to end those deeply recursive functions and return the result directly to the father function.(The one called this function) I know you can use return. But it seems like return can only bring you to the outer function which is still way too far to get to the exit and return the result. Anyone knows how should i do. Thanks
Update:I want to traverse a binary tree to search for a specific node. It's written in C++ and done in a recursive manner. So when job is done i want to jump out directly and return the node pointer rather than return to the outer recursion layer by layer. How could i do. There isn't any code pasted here simply because i can't even figure out how to code, thanks.
2nd Update: Maybe i didn't say it quite clear. Apologize for that. I mean sometimes you just know there is only one node matches in the tree and when that node is reached you just want to return the result to the caller function and not bother to have more recursion. I just wonder if there is some tricks you can bypass the C++ execution mechanism and simply end all the recursions. otherwise you have to return step by step until stack is empty. Thanks.
If your recursive definition is correct to begin with, then everything will just work fine.
Consider this:
// Just an example to demonstrate recursion:
#include <vector>
#include <iostream>
int Size(std::vector<int> const &v)
{
if (v.empty())
{
// size of empty vector = 0
return 0;
}
else
{
// size of non-empty vector = 1 + size of sub-vector
// starting from 2nd element:
return 1 + Size(std::vector<int>(v.begin() + 1, v.end()));
}
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::cout << Size(v) << "\n"; // prints 3
}
Perhaps what you really need is a way to handle special error situations where you cannot return normally. In such cases, I've often found exceptions to be a pragmatic solution.
int RecursiveFunction(int arg)
{
// ...
return RecursiveFunction(/* ... */);
// ...
// special error:
throw std::runtime_error("special error");
}
void StartRecursiveFunction()
{
try
{
int i = RecursiveFunction(start);
}
catch (std::runtime_error const &exc)
{
// error
}
}
Of course, you should not abuse exceptions to return values in the normal program flow.
You could, for example, return a bool true when you reach the desired node, and a bool false otherwise. Then, in the transversing code, check to see if the search was succesful for each child node before searching the next. If it was, you can return true again, and so on. No extra nodes are searched.
The reason why executing a tree of recursive calls is such a costly operation is because of the width of the tree, not the height. The width increases exponentially where the height is logarithmic.
This means that you can walk back the path from the leaf to the root using returns very easily. For example let's say that you find the result when you reach the 1000000th call. The return chain that retrieves the result back to the top will just be log2(1000000) ~= 20 calls.
You can nontheless use some sort of global data structure to retrieve the result "faster", but it is a very inconsequential faster, and probably not the most elegant and readable solution.
TL;DR: Help me pass vector array input into a function that originally took in int pointers and ints.
I am in a college class that is learning about well-known algorithms. In this class, we use C++ to code the given algorithms. There was no pre-req class to learn C++, so my knowledge is pretty low when it comes to some of the major stuff with programming.
My problem: I have to create a program that takes an input file, sorts it with the user's choice of sorting algorithm, and write the results to an output file. My original code that works perfectly uses an input file of 20 items, placed into an array of length 20, and sorts no problem with each individual sorting algorithm.
Since last night, the only thing I have changed is that my input goes to a vector array, since the teacher will give us files of varying length (10 items to 1,000,000 items). I have four sorting algorithms that need to sort these given input files. Only one of them works, and it does not pass any variables into the function.
The other 3 originally passed in array pointers and other variables, however they do not work with my new input now going to a vector array instead of an int array. I know that what I am passing in needs to be changed, but I have no idea how to do this correctly. I have tried many different ways from sources found on the internet (with pointers and references), but I have had no luck. Here is some snipets of the code I'm using.
vector<int> A;
void insertionSort() // This works no problem as is.
void split(int* A, int* B, int low, int high) //code for Merge-Sort
{
//recurisvely calls split() and splitMerge()
}
void splitMerge(int* A, int* B, int low, int mid, int high) // more code for Merge-Sort
{
// more code for Merge-Sort
}
//quickSort() and countSort() also pass ints and do not work either.
//small part of main()
for (i = 0; unsorted >> temp; i++)
{
A.push_back(temp);
cout << A[i] << "\n";
length++; //I use int length extensively in for-loops in my functions
}
Last thing. I do not get an error when trying to run the Merge-Sort. It just freezes my console window.
conversion from vector to array is done this way
vector vInts;
...fill the vector
int * intArr=vInts[0]
so you don't need to modify your code too much
I believe there is not enough code to make an accurate prediction on where the error may be, but I think the problem is that the sorting algorithms is doing something like A++ with you pointers to access the next member.
Because arrays store the pointer to the next array inside the object and not on adjacent cells of memory, your algorithms are cycling through stuff they shouldn't.
If this is the case, the solution to your problem is to use an iterator instead of a pointer.
void split(A.begin(), B.begin(), int low, int high)
So, I have a problem with this sorting function, that I wrote to sort struct.
My initial thought was to have a while cycle until there is no changes happening, and inside have for cycle that goes through an array[10], comparing two elements that are next to each other. If next element is larger than previous one, they are exchanged, and iterator thrown back to zero.
Everything kind of works, except for the first element, which is not highest. From second to last, everything is fine.
Any pointers, to where I have made a mistake? Code seems fine to me...
I know I could have used <algorithm>, but I am supposed to write my own function for this.
void izvadaPecRez(Pari masivs[])
{
Pari temp;
bool change;
int i;
while(change!=false)
{
for(i=0;i<10;i++)
{
if(masivs[i+1].kopejais>masivs[i].kopejais)
{
temp=masivs[i];
masivs[i]=masivs[i+1];
masivs[i+1]=temp;
change=true;
i=0;
}
else
{
change=false;
}
}
}
for(i=0;i<10;i++)
printone(masivs, i);
}
i=0 is going to happen right before the increment in the for loop runs, so the effect of the statement will be that i==1 in the next loop. The easiest way to get your intended behavior is to just break from the for-loop after you swap the elements (don't worry, it'll only break the for-loop, not the while-loop). You should also just set change=false at the top of the while-loop, rather than setting it whenever you don't swap elements.
Use this code instead for sorting (still untested):
#include<array>
#include<functional>
#include<algorithm>
std::array<Pari,100> masivs;
auto compare=[](const Pari& a, const Pari& b) {return a.kopejais<b.kopejais;};
std::sort(masivs.begin(), masivs.end(), compare);
Here, instead of a normal array, std::array is used. Next, a custom comparison lambda-function is defined and passed to std::sort.
I don't know whether it does exactly the same as your code, but at least will sort your classes according to the entry kopejais.
EDIT: Here is a version of your code which should work faster than the one in the accepted answer:
void izvadaPecRez(Pari masivs[])
{
bool change=true;
while(change==true)
{
change=false;
for(int i=0;i<10;i++)
{
if(masivs[i+1].kopejais > masivs[i].kopejais)
{
std::swap(masivs[i], masivs[i+1]);
change=true;
}
}
};
for(i=0;i<10;i++)
printone(masivs, i);
}
The reason is that you are not repeatedly looping over already ordered parts of the array, which is done by using break after the swap.