Merging multiple sorted arrays using min heap - c++

Looking to implement a function to merge multiple sorted arrays (of the same size) using STL's min heap. Here's what I have so far:
struct node{
int element; // the actual element that is being stored
int index; // array index from where the element was taken
int next; // next index
node(int x, int y, int z){
element = x;
index = y;
next = x;
}
bool operator<( const node & d ) const {
return element < d.element;
}
};
void multiway_merge(vector<vector<int> >& input_lists, vector<int>& output_list){
// n represents the number of unordered sublists and m is the number of integers comprising each sublist
size_t n = input_lists.size();
size_t m = input_lists[0].size();
int element;
vector<node> heap;
heap.reserve(m);
// loading first element of each sub-array into heap: (believe is correct)
for(int i = 0; i < n; i++){
node current(input_lists[i][0], i, 1);
heap.push_back(current);
}
make_heap(heap.begin(), heap.end());
for(int j = 0; j < (n*m); j++){
node root = heap[0];
output_list[j] = root.element;
if(root.next < m){ // if the next element isn't bigger than the array itself...
root.element = input_lists[root.index][root.next];
root.next += 1;
}
else root.element = INT_MAX; // problem is here
heap[0] = root;
make_heap(heap.begin(), heap.end());
}
}
My output is generally one of the inputted numbers and then 2147483647 (INT_MAX) for the rest of the output. I commented where/why this happens above, but overall I'm very confused on how to move within the for loop to the next element and continue going through the vectors to add more elements to the output.
Any help would be greatly appreciated!!

Related

cpp - Implement a merge sort function without using void return type (recursively)

I intend to create a recursive merge sort function that returns a pointer to the sorted array. Below is my implementation of the program.
The output produced by the code mostly consists of garbage memory locations. Since it is a recursive function, I'm having trouble debugging it. What scares me is whether I have understood pointers, arrays and their interconversion incorrectly. It would be really helpful if someone could take a look at the code and tell me my mistake.
Function that prints an array given a pointer to its first element
void printArr(int *arr, int n){
int *ptr = arr;
for(int i = 0; i < n; i++){
cout << *ptr << " ";
ptr++;
}
cout << endl;
}
Merge Sort function
Here p is the pointer to the given array, n is the length of the array. l and r are the indices of the first and last element of the array respectively.
// returns pointer to the sorted array
int* mergeSort(int *p, int n, int l, int r){
if(l >= r){
return &p[l];
}
int mid = l + (r-l)/2;
int *leftArray = mergeSort(p, n, l, mid);
int *rightArray = mergeSort(p, n, mid+1, r);
int n1 = mid - l + 1;
int n2 = r - mid;
int sortedArray[n1+n2];
int *ptr = sortedArray; // pointer to the sorted array
int p1 = 0; // left array index pointer
int p2 = 0; // right array index pointer
int idx = 0; // sorted array index pointer
int flag = 0; /* flag = 1 => all elements of left array have been placed into the sorted array ; flag = 2 => all elements of right array have been placed into the sorted array */
// putting elements into the sorted array
for(int i = 0; i < n1+n2; i++){
if(p1 == n1){
flag = 1;
break;
}
if(p2 == n2){
flag = 2;
break;
}
if(*(leftArray+i) > *(rightArray+i)){
sortedArray[i] = *(leftArray+p1);
p1++;
idx++;
}
else{
sortedArray[i] = *(rightArray+p2);
p2++;
idx++;
}
}
if(flag == 1){
// put remaining elements of right array into the sorted array
for(int i = idx; i < n1+n2; i++){
sortedArray[i] = *(rightArray+p2);
p2++;
}
}
if(flag == 2){
// put remaining elements of left array into the sorted array
for(int i = idx; i < n1+n2; i++){
sortedArray[i] = *(leftArray+p1);
p1++;
}
}
// return the sorted array
return ptr;
}
Main function
int main(){
int arr[] = {7,2,1,5};
int n = sizeof(arr)/sizeof(int);
int *p = arr;
cout << "Original array: ";
printArr(arr, n);
int *f = mergeSort(arr, n, 0, 3);
cout << "New array: ";
printArr(f, n);
}
Your code have returned the local array's address, which is invalidated after function returned. Then gabarage data is printed:
int sortedArray[n1+n2];
int *ptr = sortedArray; // pointer to the sorted array
Change into
int *ptr = new int[n1 + n2];
auto sortedArray = ptr;
Then we get a non-garbage value, but we hit memory leak and it's hard to deal with memory deallocation since the retuned pointer may point to the array p under certain boundary conditions.
So return pointer is not a good design, and it just wastes the API call to allocate memory and deallocate memory. It's better to split the function into two: the first one allocates a temporary buffer, and the second one handles sorting with the buffer as a parameter and calls itself with a recursive. Or just sort in place, totally avoid the temporary buffer.

insertion sort algorithm using a second array C++

Trying to understand the insertion sort algorithm..
My algorithm looks like this currently:
void insertionSort(int *array, int N) {
int value;
int hole;
int *array2;
for (int i = 1; i < N - 1; i++) {
value = array[i]; //next item to be inserted in array 2
hole = i;
while (hole > 0 && array[hole - 1] > value) {
array[hole] = array[hole - 1];
hole = hole - 1;
}
array[hole] = value;
}
}
My algorithm works for sorting arrays, however I now need to change it so that I build up a new sorted array (array2) one element at a time, rather than just working with the original array.
Is there a simple way to implement this given my completed algorithm?
Thanks.
You can use the following method:
int *array2 = calloc(N, sizeof(int));
for(var index = 0; index < N; index++)
{
array2[index] = array[index];
}
and after that use array2 instead of array
then just change the prototype of your function to int *insertionSort
All remaining is to return array2 at the end of task
But be aware of memory leak: https://en.wikipedia.org/wiki/Memory_leak

How to delete one data line from a structure array ? (with index)

I am trying to make a function, which deletes one line from a structure array, I give function the index of line I want to delete and the structure array. E.g. we have structure array :
Structure
{
string First;
string Second;
string Third;
string Fourth;
string Fifth;
}
Structure array :
Structure A[100];
int n;
So there are five string type elements in this structure array :
A[i].First A[i].Second A[i].Fourth A[i].Fifth // i is the index
Our function is like this :
void Delete(Structure A[], int index, int & n)
{
Structure t;
for (int i = index; i < n-1; i++)
{
t = A[i];
A[i] = A[i + 1];
A[i + 1] = t;
n--;
}
}
So I give function index and I want the function to delete all elements of my structure array with that index ( so how can I take like the whole "line" of those elements, instead of deleting them one by one ?)
A[index].First A[index].Second A[index].Third A[index].Fourth A[index].Fifth
The function however doesn't work. Can you give me some tips/advises/suggestions, please ? Thanks in advance.
At first level, your question is basically: how to remove a line from an array whose used size is stored in an external variable (passed here as n)
The signature of your function is correct, the implementation is not. It should be:
void Delete(Structure A[], int index, int & n)
{
// eventually control index >= 0 and index < n...
n -= 1;
for (int i = index; i < n; i++)
{
A[i] = A[i + 1];
}
}
If you have a recent version of C++ that support move semantics, you could speed up the operation by moving the strings instead of copying them:
n -= 1;
for (int i = index; i < n; i++)
{
A[i] = std::move(A[i + 1]);
}

How to sort one array and get corresponding second array in C++? [duplicate]

This question already has answers here:
sort one array and other array following?
(3 answers)
Closed 7 years ago.
I have two arrays in same size. And want to sort one of the array normally and then sort the next array elements accordingly.
Let's say we have two arrays
e[] = {4,2,3,7,6,8}
s[] = {2,0,4,3,7,9}
First I want to sort array e normally, Then change the element positions of s array according to the changed element positions of e.
This should be the final result
e[] = {2,3,4,6,7,8}
s[] = {0,4,2,7,3,9}
How should I do this? Should I use a class object with these two as private members and then proceed? If so, how to do that?
Create a single array (or vector) of std::pair objects, where first is from the first array and second from the second. Then just use std::sort with a custom comparator function that uses only second from the pair for comparison. Iterate over the sorted array (or vector) and split up into the original arrays.
Note: If the values in each array are tightly coupled then consider putting them in a structure or class instead of using two (or more) distinct arrays.
What I think is use std::map
Assign array e element as the key
And corresponding array s element as the value.
Then sort the may by key
Go trough the map and get the values one by one
If you do this in a class, you can create an array of indices and sort the indices according to the values in e[]. If not doing this within a class, and for a more general approach, create an array of pointers to e[], then sort the pointers according to e[]. Then reorder e[] and s[] according to the pointers, converting the the sorted pointers to an index by using array_of_pointers[i] - &e[0] (or just array_of_pointers[i]-e). You could write your own sort, or use qsort, std::sort, or std::stable sort to sort the array of pointers, with a compare function that compares using dereferenced pointers (compares the values pointed to). Example C code using qsort and reorder in place logic with O(n) time complexity:
int compare(const void *pp0, const void *pp1)
{
int i0 = **(int **)pp0;
int i1 = **(int **)pp1;
if(i0 > i1)return -1;
if(i0 < i1)return 1;
return 0;
}
int main()
{
int e[...];
int s[...];
int *pe[...];
size_t i, j, k;
int te, ts;
/* ... */
/* create array of pointers to e[] */
for(i = 0; i < sizeof(e)/sizeof(e[0]); i++)
pe[i] = &e[i];
/* sort array of pointers */
qsort(pe, sizeof(e)/sizeof(e[0]), sizeof(pe[0]), compare);
/* reorder e[] and s[] according to the array of pointers */
for(i = 0; i < sizeof(e)/sizeof(e[0]); i++){
if(i != pe[i]-e){
te = e[i];
ts = s[i];
k = i;
while(i != (j = pe[k]-e)){
e[k] = e[j];
s[k] = s[j];
pe[k] = &e[k];
k = j;
}
e[k] = te;
s[k] = ts;
pe[k] = &e[k];
}
}
/* ... */
return 0;
}
If you don't want to use other Data structures and stick with the two different integer arrays..
Following code snippet will help you
int _tmain(int argc, _TCHAR* argv[])
{
int e[] = {4,2,3,7,6,8} ;
int s[] = {2,0,4,3,7,9} ;
int temp ;
int Array_Size = 6 ; // don't use hard coded value here, rather calculate from array size
for(int i = 0 ; i < Array_Size ; i++)
{
for(int j = i+1 ; j < Array_Size ; j++)
{
if(e[i] > e[j])
{
// Swap elements in first array
temp = e[j] ;
e[j] = e[i] ;
e[i] = temp ;
// As you want both arrays in sync
// Swap elements in second array here itself
temp = s[j] ;
s[j] = s[i] ;
s[i] = temp ;
}
}
}
return 0;
}
It is quite simple when we use structure.Your basic task is to sort two arrays. I want to suggest one method regarding it. Use a structure having two variables x and y which are used here for two arrays. Make two array of objects of this structure.
struct Point
{
int x,y;
};
struct Point arr[n];
After providing entries to the array of structure objects, make use of STL function
sort(arr,arr+n,myfun);
where myfun is function to sort according to ur need and it is defined as
bool myfun(struct Point a,struct Point b)
{
if(a.x<b.x)
return true;
else
return false;
}
And here is the complete program in c++
#include <bits/stdc++.h>
using namespace std;
struct Point{
int x,y;
};
bool myfun(struct Point a,struct Point b)
{
if(a.x<b.x)
return true;
else
return false;
}
int main()
{
int n; //n is the number of elements of array
cin>>n;
struct Point arr[n];
//Enter first array
for(int i=0;i<n;i++)
cin>>arr[i].x;
//Enter second array
for(int i=0;i<n;i++)
cin>>arr[i].y;
//sorting with the help of myfun
sort(arr,arr+n,myfun);
//now print the arrays
for(int i=0;i<n;i++)
cout<<arr[i].x<<" ";
cout<<"\n";
for(int i=0;i<n;i++)
cout<<arr[i].y<<" ";
return 0;
}
void bubbleSort(int e[], int s[], int n) {
bool swapped = true;
int j = 0;
int tmp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < n - j; i++) {
if (e[i] > e[i + 1]) {
tmp = e[i];
e[i] = e[i + 1];
e[i + 1] = tmp;
tmp = s[i];
s[i] = s[i + 1];
s[i + 1] = tmp;
swapped = true;
}
}
}
}

Inserting an element into an array

How can I make an inset method that will add a number into the array in the correct order?
void addElement(int table[], int element, int length) {
int x = 0;
int temporary=0;
cout<<length<<endl;
if(length == 1) {
table[0] = element;
}
else {
if(length == 2) {
if (table[0] > element) {
int temp = table[0];
table[0] = element;
table[1] = temp;
}
else {
table[1] = element;
}
}
else {
for(int i = 0; i< length && x == 0; i++) {
if(element<table[i] && element>=table[i-1]) {
for(int y = i; y<length; y++) {
temporary = table[y+2];
int temp = table[y];
table[y] = element;
table[y+1] = table
}
}
}
}
}
}
This is as far as I have gotten. In my main class I have worked it out so that array is increased by 1. So there is one open space at the end of the array for everything to be pushed back by 1.
You can scan the array from back to front, moving values up until you find the correct insertion point.
void addElement(int *table, int element, int length)
{
int i = length - 1;
for (; i > 0 && table[i-1] > element; --i)
{
table[i] = table[i-1];
}
table[i] = element;
}
Write a shiftElements function, write a findIndexOfFirstGreaterThan function, then in addElement - find the index, if -1 then put in last slot, else shift elements using index, then a[index]=elem;
Draw yourself an example, then work out a list of very simple steps required to do what you want.
Then write code that does those steps.
Im not sure if this is what your looking for, but I think you want something that adds an element depending on its integer value. Also, I do not have access to a compiler at this moment so there might be a couple of errors. The code below is just written to give you a brief idea of what you could do, but probably not a perfect solution to your problem.
int addElement (int element, int array [], int length)
{
vector <int> vectorOfInts; //vector to store current order of ints
vector <int> vectorOfArrangedInts; //vector to store arranged order
for (int counter = 0; counter < length; counter ++) //loop to fill the array with values
{
vectorOfInts.push_back (array [counter]);
}
for (int counter = 0; counter < vectorOfInts.length(); counter ++) //loop through all elements
{
int temp = 0; //stores temp value of biggest number found at a specific moment
int elementIndex; //stores indexes
for (int counterTwo = 0; counterTwo < vectorOfInts.length(); counterTwo ++) //loop through all elements to find the biggest array
{
if (vectorOfInts.at (counterTwo) >= temp) //if value is bigger than current biggest number
{
temp = vectorOfInts.at (counterTwo); //change temp value
elementIndex = counterTwo; //remember index
}
}
vectorOfArrangedInts.push_back (vectorOfInts.at(elementIndex)); //add the biggest number to the arranged values
vectorOfInts.erase (vectorOfInts.begin() + elementIndex); //remove the biggest element
}