Implementing own quicksort on dynamic array - c++

I have to implement my own sort on a dynamic string array, e.g. of such array is:
string * sortArray;
I then read in the size of the array from a text file and make the array as long as needed and fill it. So, I have...
sortArray = new string[_numberOfNames];
for(int i = 0; i < _numberOfNames; ++i){
sin >> _data[i];
}
Now I need to create my own sorting method and I thought I'd go with quicksort. My problem is, I'm not sure how to go about it.
When I choose a pivot, how can I then go about setting up two more dynamic string arrays to put the lower values and highers values in to, then recurse on? There is no way of knowing before hand how big each array needs to be before I start putting values into them.
I thought I could do something like define the size of each array as being the same as the array being sorted, and then some how remove any unwanted empty spaces from the end, but I'm not sure this is possible?
Any help would be much appreciated.
P.S. I know about the std::sort, I already have this in the program, I'm just trying to implement a sort myself.

Two options as from the comments above:
1.) Use std::vector. There you can have variable size arrays.
2.) Use an "in place" version of quicksort that does the sorting in your original array. See http://en.wikipedia.org/wiki/Quicksort#In-place_version

Lets say you have array size N
and you pivot value is x
what you should do is like that, have two pointers one to the beginning(0) and one to the end (N-1). they should both move to the middle. when ever the beginning pointer value is greater than x and the end pointer value is lower than x switch their values. after you finished and placed x in his new location (where the two pointers met) continue recursionally for the part left to x and right to x.

Related

How to insert a new value into a sorted array (using two arrays); C++

I am relatively new to C++, and currently writing a function that involves inputting a number of new value(s) into a sorted array. When the new value is put into the array, it needs to maintain it's sort in ascending order. This has to be done using two arrays (the original array, and a "destination" array that will contain the new, sorted value). I'm completely at a loss on how to go about this.
Everything that I have to do must be within the iostream and iomanip libraries.
This is all I have so far:
int insert_into_sorted (int source[], int source_len, int destination[], int new_elem){
int offset = 0;
for (int i = 0; i <= source_len; i++)
{
if (new_elem < source[i])
{
source[i] = destination[i + offset];
}
else
{
return 1;
}
}
}
I don't entirely know what I'm doing, at all. I have made a for loop, and an if statement within that for-loop.
When I execute the program, I input a test value. Based on what test value I enter, a certain new value is inputted.
EX: If I do test 1, it inputs a value of 15 within an array of 10,20. The 15 needs to go into the array of 10,20 while also being in ascending order.
However, my output contains:
Original array (10,20)
New array (-1,-1, 4255009);
I have tried rearranging statements, different return values, with slightly different outputs--but again, I'm so lost that I'm not sure what this is even doing in terms of how my program is running. Because it's a function and I cannot edit main, it's a bit difficult to test what is happening step-by-step.
I'll assume that destination is large enough to contain the additional element.
You will probably want to first compare new_elem to each element of source before copying. If source[i] > new_elem, then you'll want to copy new_elem to destination instead of source[i] - this is to ensure that new_elem gets copied before an element larger than it and after an element smaller than it (which is how sorting works), and set a flag to tell the function to copy the rest of the elements regularly - that way, you don't keep recopying new_elem over and over again.
The code would probably look something like this (I'm only giving the pseudocode, not the actual code itself):
set `new_element_copied` to False
for each element in `source`:
if the current element > `new_elem` and `new_element_copied` is not True:
copy `new_elem` to `destination`
copy current element to `destination` //so as not to skip an element
set `has_new_element_been_copied` to True
else
copy current element to `destination`
(the ` characters indicate variable names)
Also, make sure that when you're iterating over an array in C++, you use < not <=. Arrays are 0-indexed, so arr[10] would get the 11th element in arr.
Edit
If you don't end up copying new_elem in your for loop, make sure to copy it at the end by checking if new_element_copied is still False:
set `new_element_copied` to False
for each element in `source`:
...
if `new_element_copied` is False: //indicates element was not copied
copy `new_elem` to `destination`
Edit 2: Make sure to keep a seperate variable for the index of destination, as using the same index for both source and destination will screw you up

Compare each element of a 2D array with the rest C++

I'm new to C++, and what I have to do is to write a method that checks if a 2D array contains any duplicate items.
So for example, I have a matrix[3][4], I've been able to compare the first element [0][0] with the rest, till the last one [2][3].
The problem is that I don't know how to proceed, what I should do is that the method then compares the element [0][1] with the rest (except with the previous one and itself of course) and etc..
First of, the fact that it's a 2D array is irrelevant in this context; you want to find duplicates across the entire array, so you'd be better of with 1-dimensional indexing anyway. Coincidentally, that's a suggested way of handlings two-dimensional arrays in C++.
So assuming you can put the indices in some order, the general idea is to check every element with all subsequent elements. This will give you O(n2). A pseudocode is, unsurprisingly, two loops, and is a common pattern used e.g. for collision detection:
for (iterA = 0; iterA < num - 1; iterA++) {
for (iterB = iterA + 1; iterB < num; iterB++) { // note how iterB starts one further
if (*iterA == *iterB)
return true; // found a duplicate
}
}
In case of a 2D array, the *iterA dereference can be replaced with a function that breaks up the composite 1-dimensional index into two components, e.g. with i % width, i / width. This is, again, a very common pattern.
That being said, why bother? Make an std::set, start putting elements one-by-one and call find before every insert. If find returns something, break.

How can I test whether an array element is defined or not (where element can be defined as 0)?

DISCLAIMER: I'm very new to C++ so I'm sorry if this is a stupid question!
I'm trying to read in data to an 1000 element array (double) and then if there are less than 1000 data points to read in ignore the excess elements for the rest of my program.
I've defined a 1000 element array and read in the data and now want to carry out a function on each element which has been defined by the read in data point. How do I test if an element is defined yet? I would use a Boolean algebra test i.e. if(array[i]) {\\function} but the data points can be any natural number including zero, so I don't know if this would work. How would I solve this problem?
The most typical approach to the problem of "the number of things in my array is not fixed ahead of time" is to have a variable that keeps track of how many things are actually in the array. Then, you just loop over that many things.
Since you add the C++ tag, you can (and should) use the vector class to manage everything for you — and you even get the added benefit that it can grow beyond 1000 elements should you happen to have more than that.
(aside: if you insist on sticking with a 1000-long array, you really should make sure you do something appropriate should you actually get more than 1000 data points)
You could initialize your array with a sentinel value like NAN (i.e., not a number):
double array[1000];
std::fill(std::begin(array), std::end(array), NAN);
Then fill sequentially your array:
array[0] = 1.2;
array[1] = 2.3;
array[2] = 3.4;
And then break the loop as soon as this value is met:
for(int i(0); i < 1000; ++i) {
if(isnan(array[i])) break;
function(array[i]);
}
LIVE DEMO

Replacing For loop with memcopy, memmove, or std:copy?

I've got shift function where i an continuously sending it new data points and it will shift my points by an offset of 1. This is to achieve a "graphical shifting" where the points represent points on a graph.
The shifting function is the following:
void Chart_Buffer::ShiftData()
{
for(int index = 0; index < (_channel_Samples - 1); ++index)
{
_sample_Points[index].y = _sample_Points[index + 1].y;
}
return;
}
The problem with this is that it is running through a huge array of up to 800 data points and it does this every time for every new data point added, so i wanted to see if i can optimize this process by shifting all values out by an offset of 1 without running through a for loop. I looked at implementations of memcopy, memmove, and std::copy, but i cant figure out how to use them for my purpose.
Basically, if i have elements 0-799 in the array, i want to shift elements 1-799 by 1 so that i have 0-798 and then just add the new element to the array.
Edit: _sample_Points is type tagPOINT with the following structure:
typedef struct tagPOINT
{
LONG x;
LONG y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
It's hard to give a firm answer to this without knowing what you are doing with _sample_Points. But I believe that I can firmly say that copying every element in the array down one is an expensive approach.
In the best case: You just need to access the front of the array and add to the back of the array. If that's the case you're describing a queue.
To add a new element to the back of a queue use: push
To inspect the front element use: front
To "copy everything down one" (just delete the front element) use: pop.
Otherwise you'd be in the case where: You need random access to the array. If that's the case you can still get potentially better performance from a deqeu.
To add a new element to the back of a deque use: push_back
To inspect the front element use: front
To "copy everything down one" (just delete the front element) use: pop_front
So if you use a queue for your _sample_Points Chart_Buffer::ShiftData could be replaced by _sample_Points.pop().
If you use a deque for your _sample_Points Chart_Buffer::ShiftData could be replaced by _sample_Points.pop_front().
It looks like that you are looking for a std::deque. It is a double ended queue, which means you can pop an element from the back and push on the front.
If what you are looking for is to keep the elements of your array in a certain order, this will help you do just that.
Now if you also want to have them contiguously on memory, then you could do it like this:
memmove(array+1, array, sizeof(element)*(array_size-1));
array[0] = new_element;
You cannot do this without less operations than you are already doing, whether you spell all of them or you call an algorithm. The problem is that the operation is not what you described initially, it is not shifting the data, but shifting part of the data (only the y coordinate) but leaving the other half as it is.
If you don't want to spell out the operation, you can play with the transform algorithm in a way similar to the answer by id256, but I am not sure whether that is an improvement really, the loop in the question is easier and cleaner than the transform...
If it is an acceptable amount of refactoring of your code, you could also let go of tagPOINT and instead of having one _sample_Points, have two arrays, one for the x and one for the y. Then you can memmove() the array of ys. Like:
LONG _sample_Points_x[DIMENSION];
LONG _sample_Points_y[DIMENSION];
void Chart_Buffer::ShiftData() {
memmove(_sample_Points_y, _sample_Points_y + 1, (DIMENSION-1) * sizeof _sample_Points_y[0]);
}

push_back/append or appending a vector with a loop in C++ Armadillo

I would like to create a vector (arma::uvec) of integers - I do not ex ante know the size of the vector. I could not find approptiate function in Armadillo documentation, but moreover I was not successfull with creating the vector by a loop. I think the issue is initializing the vector or in keeping track of its length.
arma::uvec foo(arma::vec x){
arma::uvec vect;
int nn=x.size();
vect(0)=1;
int ind=0;
for (int i=0; i<nn; i++){
if ((x(i)>0)){
ind=ind+1;
vect(ind)=i;
}
}
return vect;
}
The error message is: Error: Mat::operator(): index out of bounds.
I would not want to assign 1 to the first element of the vector, but could live with that if necessary.
PS: I would really like to know how to obtain the vector of unknown length by appending, so that I could use it even in more general cases.
Repeatedly appending elements to a vector is a really bad idea from a performance point of view, as it can cause repeated memory reallocations and copies.
There are two main solutions to that.
Set the size of the vector to the theoretical maximum length of your operation (nn in this case), and then use a loop to set some of the values in the vector. You will need to keep a separate counter for the number of set elements in the vector so far. After the loop, take a subvector of the vector, using the .head() function. The advantage here is that there will be only one copy.
An alternative solution is to use two loops, to reduce memory usage. In the first loop work out the final length of the vector. Then set the size of the vector to the final length. In the second loop set the elements in the vector. Obviously using two loops is less efficient than one loop, but it's likely that this is still going to be much faster than appending.
If you still want to be a lazy coder and inefficiently append elements, use the .insert_rows() function.
As a sidenote, your foo(arma::vec x) is already making an unnecessary copy the input vector. Arguments in C++ are by default passed by value, which basically means C++ will make a copy of x before running your function. To avoid this unnecessary copy, change your function to foo(const arma::vec& x), which means take a constant reference to x. The & is critical here.
In addition to mtall's answer, which i agree with,
for a case in which performance wasn't needed i used this:
void uvec_push(arma::uvec & v, unsigned int value) {
arma::uvec av(1);
av.at(0) = value;
v.insert_rows(v.n_rows, av.row(0));
}