Sort merged array consisting of sorted arrays - c++

I got two sorted arrays e.g. (3,4,5) and (1,3,7,8) and I got the combined sorted array (3,4,5,1,3,7,8).
Now I would like to sort the already combined array, without splitting it, but by overwriting it, by making use of the fact that it consists of 2 arrays which had already been sorted. Is there any way of doing this efficiently? I know there are a lot of threads about how to do this, by iterating through the sorted arrays and then putting the values into the new array accordingly, but I haven't seen this type of question anywhere yet. I would like to do this in c, but any help / pseudocode would be very kindly appreciated. Thanks!
Edit: The function which would do the sorting, would only be given the combined array and (maybe ) the length of the other two arrays if needed.

If you already have the original sorted arrays, the combined array (note it is not sorted) doesn't really help, except in that your destination storage is already allocated.
There's a well-known and very simple algorithm for merging two sorted ranges, but you can just use std::merge instead of coding it yourself.
Note that only works for non-overlapping input & output ranges: for your amended question, use std::inplace_merge, with the middle iterator set to the first element from your second sequence:
void sort_combined(int *array, size_t total, size_t first) {
std::inplace_merge(array, array + first, array + total);
}
// and use it like
int combined[] = {3, 4, 5, 1, 3, 7, 8};
const size_t first = 3;
const size_t second = 4;
const size_t total = 7; // == sizeof(combined)/sizeof(*combined)
sort_combined(combined, total, first);

Related

Sorting a structure of arrays [duplicate]

This question already has answers here:
Sorting zipped (locked) containers in C++ using boost or the STL
(5 answers)
Closed 4 years ago.
I have some data laid out as follows:
size_t num_elements = //...
some_type_t *data = //...
int *scores = //...
Each element data[i] has a corresponding score in scores[i]. I would like to sort both data and scores, using the array of scores to order the data.
For example, for the data:
data = {'d', 'g', 'i', 'a', 'p'}
scores = {3, 5, 1, 2, 4}
the sorted version would be
data = {'i', 'a', 'd', 'p', 'g'}
scores = {1, 2, 3, 4, 5}
Is there a way to do this with the C++ standard library?
I would prefer not to need to include Boost or libraries that have not yet been standardised.
I would also like to avoid unnecessarily copying the the data. This includes converting it to an array of structures.
Assuming there isn't a reason to NOT combine the two data arrays, the simplest answer would be to merge them into a struct or a class (likely the former) with an overloaded operator. Then you can define an array of these structures/classes that will bind the data together so the data and score are moved together.
struct ScoredData
{
some_type_t data;
int score;
bool operator<(const ScoredData& right)
{
return this->score < right.score;
}
}
(This example could be extended by making some_type_t a template parameter)
If combining these in this way is not acceptable, you may find success defining an iterator that mimicks this behavior.
One other way to do this is to create an array of indexes (initialize it with 0,1,2,3...) and sort it using the score[a] < score[b] comparison.
Then you need to rearrange the scores and the data arrays according to the indexes. For example, if indexes[0] = 3 after sorting, you need to move elements score[0] = score[3]; data[0] = data[3].
I do not see a way to avoid copying when you rearrange, unfortunately.
can you group the elements in a new array of these couples, then sort it using sort and comparing at the right couple element, then update the initial arrays from the sorted array of couple ?
better :
you create a vector of couples made by the score values and the index 0 for the first couple, then 1 for the second, 2 for the third etc So you do not copy the datas
you qsort that array of couples considering the score part, after you just have to look at the new order of the indexes in the couples to sort scores and data easily updating them

Sorting a two-dimensional array of characters? C++

I'm trying to sort a 10X15 array of characters, where each row is a word. My goal is to sort it in a descending order, from the largest value word at the top, at array[row 0][column 0 through 14] position, and the smallest value word at the bottom array[row 9][column 0 through 14]. Each row is a word (yeah, they don't look as words, but it's to test the sorting capability of the program).
To clarify: What I need to do is this... considering that EACH row is a whole word, I need to sort the rows from the highest value word being at the top, and the lowest value word being at the bottom.
Edit:
Everything works now. For anyone who has a similar question, look to the comments below, there are several fantastic solutions, I just went with the one where I create my own sort function to learn more about sorting. And thanks to all of you for helping me! :)
You are using c++ so quit using arrays and begin with stl types:
Convert each row into a string:
string tempString
for (int i = 0; i < rowSize; ++i) {
tempString.pushBack(array[foreachrow][i])
}
add them to a vector
std::vector<std::string> sorter;
sorter.push_back(tempString);
Do that for each row.
std::vector<std::string> sorter;
for each row {
for each coloumn {
the string thing
}
push back the string
}
Then sort the vector with std::sort and write the vector back into the array (if you have to but don't because arrays suck)
As usual, you need qsort:
void qsort( const void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
That takes a void pointer to your starting address, the number of elements to sort, the size of each element, and a comparison function.
You would call it like this:
qsort( array, ROWS, COLS, compare_word );
Where you define compare_word to sort in reverse:
int compare_word( const void* a, const void* b )
{
return strncmp( b, a, COLS );
}
Now, given that each word is 15 characters long, there may be padding to deal with. I don't have absolute knowledge that the array will be packed as 10 by 15 instead of 10 by 16. But if you suspect so, you could pass (&array[1][0] - &array[0][0]) as the element size instead of COLS.
If you are not allowed to use qsort and instead must write your own sorting algorithm, do something simple like selection sort. You can use strncmp to test the strings. Look up the function (google makes it easy, or if you use Linux, man 3 strncmp). To swap the characters, you could use a temporary char array of length COLS and then 3 calls to memcpy to swap the words.
The problem with your new code using string and vector is a simple typo:
sorter[count] = array[count+1]; should be sorter[count] = sorter[count+1];

How do I remove duplicates from a C++ array?

I have an array of structs; the array is of size N.
I want to remove duplicates from the array; that is, do an in-place change, converting the array to have a single appearance of each struct. Additionally, I want to know the new size M (highest index in the reduced array).
The structs include primitives so it's trivial to compare them.
How can I do that efficiently in C++?
I have implemented the following operators:
bool operator==(const A &rhs1, const A &rhs2)
{
return ( ( rhs1.x== rhs2.x ) &&
( rhs1.y == rhs2.y ) );
}
bool operator<(const A &rhs1, const A &rhs2)
{
if ( rhs1.x == rhs2.x )
return ( rhs1.y < rhs2.y );
return ( rhs1.x < rhs2.x );
}
However, I get an error when running:
std::sort(array, array+ numTotalAvailable);
* array will have all elements here valid.
std::unique_copy(
array,
array+ numTotalAvailable,
back_inserter(uniqueElements));
* uniqueElements will have non-valid elements.
What is wrong here?
You could use a combination of the std::sort and std::unique algorithms to accomplish this:
std::sort(elems.begin(), elems.end()); // Now in sorted order.
iterator itr = std::unique(elems.begin(), elems.end()); // Duplicates overwritten
elems.erase(itr, elems.end()); // Space reclaimed
If you are working with a raw array (not, say, a std::vector), then you can't actually reclaim the space without copying the elements over to a new range. However, if you're okay starting off with a raw array and ending up with something like a std::vector or std::deque, you can use unique_copy and an iterator adapter to copy over just the unique elements:
std::sort(array, array + size); // Now in sorted order
std::vector<T> uniqueElements;
std::unique_copy(array, array + size,
back_inserter(uniqueElements)); // Append unique elements
At this point, uniqueElements now holds all the unique elements.
Finally, to more directly address your initial question: if you want to do this in-place, you can get the answer by using the return value from unique to determine how many elements remain:
std::sort(elems, elems + N); // Now in sorted order.
T* endpoint = std::unique(elems, elems + N);// Duplicates overwritten
ptrdiff_t M = endpoint - elems; // Find number of elements left
Hope this helps!
std::set<T> uniqueItems(v.begin(), v.end());
Now uniqueItems contains only the unique items. Do whatever you want to do with it. Maybe, you would like v to contain all the unique items. If so, then do this:
//assuming v is std::vector<T>
std::vector<T>(uniqueItems.begin(), uniqueItems.end()).swap(v);
Now v contains all the unique items. It also shrinks v to a minimum size. It makes use of Shrink-to-fit idiom.
You could use the flyweight pattern. Easiest way to do so, would be using the Boost Flyweight library.
Edit: I'm not sure if there is some way to find out how many objects are stored by the Boost flyweight implementation, if there is, I can't seem to find it in the documentation.
An alternative approach to applying algorithms to your array would be to insert its elements in a std::set. Whether it is reasonable to do it this way depends on how you plan to use your items.

c++ Sorting a vector based on values of other vector, or what's faster?

There are a couple of other posts about sorting a vector A based on values in another vector B. Most of the other answers tell to create a struct or a class to combine the values into one object and use std::sort.
Though I'm curious about the performance of such solutions as I need to optimize code which implements bubble sort to sort these two vectors. I'm thinking to use a vector<pair<int,int>> and sort that.
I'm working on a blob-tracking application (image analysis) where I try to match previously tracked blobs against newly detected blobs in video frames where I check each of the frames against a couple of previously tracked frames and of course the blobs I found in previous frames. I'm doing this at 60 times per second (speed of my webcam).
Any advice on optimizing this is appreciated. The code I'm trying to optimize can be shown here:
http://code.google.com/p/projectknave/source/browse/trunk/knaveAddons/ofxBlobTracker/ofCvBlobTracker.cpp?spec=svn313&r=313
important: I forgot to mention that the size of the vectors will never be bigger than 5, and mostly have only 3 items in it and will be unsorted (maybe I could even hardcode it for 3 items?)
Thanks
C++ provides lots of options for sorting, from the std::sort algorithm to sorted containers like std::map and std::set. You should always try to use these as your first solution, and only try things like "optimised bubble sorts" as a last resort.
I implemented this a while ago. Also, I think you mean ordering a vector B in the same way as the
sorted values of A.
Index contains the sorting order of data.
/** Sorts a vector and returns index of the sorted values
* \param Index Contains the index of sorted values in the original vector
* \param data The vector to be sorted
*/
template<class T>
void paired_sort(vector<unsigned int> & Index, const vector<T> & data)
{
// A vector of a pair which will contain the sorted value and its index in the original array
vector<pair<T,unsigned int>> IndexedPair;
IndexedPair.resize(data.size());
for(unsigned int i=0;i<IndexedPair.size();++i)
{
IndexedPair[i].first = data[i];
IndexedPair[i].second = i;
}
sort(IndexedPair.begin(),IndexedPair.end());
Index.resize(data.size());
for(size_t i = 0; i < Index.size(); ++i) Index[i] = IndexedPair[i].second;
}

Customizing compare in bsearch()

I have an array of addresses that point to integers ( these integers
are sorted in ascending order). They have duplicate values. Ex: 1,
2, 2, 3, 3, 3, 3, 4, 4......
I am trying to get hold of all the values that are greater than a
certain value(key). Currently trying to implement it using binary
search algo -
void *bsearch(
const void *key,
const void *base,
size_t num,
size_t width,
int ( __cdecl *compare ) ( const void *, const void *)
);
I am not able to achieve this completely, but for some of them.
Would there be any other way to get hold of all the values of the
array, with out changing the algorithm I am using?
As Klatchko and GMan have noted, the STL function gives you exactly what you're asking: std::upper_bound.
If you need to stick with bsearch, though, the simplest solution may be to iterate forwards until you reach a new value.
void* p = bsearch(key, base, num, width, compare);
while ((p != end) && // however you define the end of the array -
// base + num, perhaps?
(compare(key, p)==0)){ // while p points to an element matching the key
++p; // advance p
}
If you want to get the first p that matches key, rather than the first one that's larger, just use --p instead of ++p.
Whether you prefer this or a repeated binary search, as Michael suggests, depends on the size of the array and how many repetitions you expect.
Now, your question title refers to customizing the compare function, but as I understand the question that won't help you here - the compare function must compare any two equivalent objects as being equivalent, so it's no good for recognizing which of several equivalent objects is the first/last of its type in an array. Unless you had a different problem, specifically concerning the compare function?
You should look into std::upper_bound
For example, to find the address of the first value > 3:
const int data[] = { 1, 2, 2, 3, 3, 3, 3, 4, 4, ... };
size_t data_count = sizeof(data) / sizeof(*data);
const int *ptr = std::upper_bound(data, data + data_count, 3);
// ptr will now point to the address of the first 4
A related function is std::lower_bound.
Yes, you can use a binary search. The trick is what you do when you find an element with the given key... unless your lower and upper indices are the same, you need to continue binary searching in the left part of your interval... that is, you should move the upper bound to be the current midpoint. That way, when your binary search terminates, you will have found the first such element. Then just iterate over the rest.
If you have a binary search tree implemented, you have tree traversal algorithms to do this. You could reach the required 'upper-bound' node and simply traverse in-order from there. Traversal is simpler than searching the tree multiple times, i.e, traversing a tree of n nodes would take n operations at most, whereas searching n times would take (n.log n) operations.