Do temporary variables stop an algorithm from being in-place? - c++

I have written an algorithm for creating the consecutive maximum list of an original list A, such that a(i+1)=max(a(i),a(i+1)).
OUT OF PLACE ALG:
void conMax(int A[], int maxA[],int n)
{
for (int i=0;i<n;i++)
{
if (A[i]>=A[i-1])
{
maxA[i]=A[i];
}
else
{
maxA[i]=A[i-1];
}
}
}
IN PLACE ALG:
void inConMax(int a[],int n)
{
int temp = -INFINITY;
for (int i=0;i<n;i++)
{
if(temp>a[i])
{
int k = temp;
temp = a[i];
a[i]=k;
}
else
{
temp=a[i];
}
}
}
Will using temporary variables within the loop to avoid using another array (maxA) stop my new alg from being in-place?
input: int a[9] = {7,5,9,23,24,6,4,19,20}
output: 7 7 9 23 24 24 6 19 20

Related

kth smallest element using min-heap

I was solving a problem of kth smallest element using min-heap but got stuck as it's always giving me the first smallest element, so I guess my extractmin function is not working correctly.My approach was to make array into a min heap data structure in which root is the minimum element and then remove k-1 smallest elements and then simply return the value of root.
#include <iostream>
using namespace std;
void swap(int &x, int &y)
{
int u = x;
x = y;
y = u;
}
int l(int p)
{
return 2 * p + 1;
}
int r(int p)
{
return 2 * p + 2;
}
void heapify(int arr[], int i, int n);
void makeheap(int arr[], int n)
{
int last = n - 1;
for (int i = (last - 1) / 2; i >= 0; i--)
{
heapify(arr, i, n);
}
}
void heapify(int arr[], int i, int n)
{
int smallest = arr[i],y=0;
if (l(i) <= n - 1 && arr[l(i)] < arr[i])
{
smallest = arr[l(i)];
}
if (r(i) <= n - 1 && arr[r(i)] < smallest)
{
smallest = arr[r(i)];
y=1;
}
if (smallest != arr[i])
{
if(y==0){
swap(arr[l(i)], arr[i]);}
else if(y==1)
{
swap(arr[r(i)],arr[i]);
}
heapify(arr, i, n);
}
}
void extractmin(int arr[], int &n)
{
swap(arr[0], arr[n - 1]);
n--;
heapify(arr, 0, n);
}
int getmin(int arr[])
{
return arr[0];
}
int main()
{
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
int k;
cin >> k;
makeheap(arr, n);
for (int i = 0; i < k - 1; i++) {
extractmin(arr, n);
}
cout << getmin(arr) << "\n";
}
}
Input:
2
6
7 10 4 3 20 15
3
5
7 10 4 20 15
4
Expected Output:
7
15
My Output:
3
4
In heapify() you use
swap(smallest,arr[i]);
That exchanges the values in smallest and arr[i]. But arr[l(i)] or arr[r(i)] is not changed. What this actually does is copy the smaller value of arr[l(i)] and arr[r(i)] into arr[i].
Also in main you do
for (int i = 0; i < k - 1; i--) {
which counts i down till it hits INT_MIN instead of counting up to k. This quickly causes the heap to be empty and the code to segfault.
PS: Why not use the std::make_heap and friends?

How do I properly implement merge sort

I have the merge sort code below which is not giving proper output.
Input : 1 7 3 9 4 5 2 6 8
Output : 1 5 2 6 7 3 8 1 9.
#include<iostream>
#include<vector>
using namespace std;
void merge(vector<int>& array,vector<int>& helper,int low,int mid,int high)
{
int size = array.size();
for(int i =0;i<size;i++)
helper.push_back(array[i]);
//helper = array; // copy vector elements i .. copying references doesnt work hence
int current = low;
int helperLeft = low;
int helperRight = mid+1;
while(helperLeft<=mid && helperRight <=high)
{
if(helper[helperLeft]<helper[helperRight])
{ array[current] = helper[helperLeft];
helperLeft++;
}
else
{
array[current] = helper[helperRight];
helperRight++;
}
current++;
}
int remaining = mid - helperLeft;
for (int i = 0; i <= remaining; i++)
array[current + i] = helper[helperLeft + i];
// copy the remaining elements from the left only and not right because right elememts are already there in dest (array) sorted.
}
void mergeSort(vector<int>&array,vector<int>& helper,int low,int high)
{
if(low < high)
{
int mid = (low+high)/2;
mergeSort(array,helper,low,mid);// sort left half
mergeSort(array,helper,mid+1,high);// sort right half
merge(array,helper,low,mid,high);
}
}
void mergeSort(vector<int>& array)
{
vector<int> helper;
mergeSort(array,helper,0,array.size());
}
int main()
{
vector<int> v;
int i =1;
v.push_back(i);
v.push_back(i+6);
v.push_back(i+2);
v.push_back(i+8);
v.push_back(i+3);
v.push_back(i+4);
v.push_back(i+1);
v.push_back(i+5);
v.push_back(i+7);
vector<int>::iterator it=v.begin();
while(it!=v.end())
{
cout<<" "<<*it;
it++;
}
cout<<endl;
mergeSort(v);
it = v.begin();
while(it!=v.end())
{
cout<<" "<<*it;
it++;
}
cout<<endl;
}
I am using C++ vectors here instead of arrays as passing size will be a problem?
Can somebody please hep me correct the mistake here?
I got the answer.The correct solution is posted below.
#include<iostream>
#include<vector>
using namespace std;
void merge(vector<int> &array,int low,int mid,int high)
{
vector<int> helper(array);
//helper = array; // copy vector elements i .. copying references doesnt work hence
int current = low;
int helperLeft = low;
int helperRight = mid+1;
while(helperLeft<=mid && helperRight <=high)
{
if(helper[helperLeft]<helper[helperRight])
{
array[current] = helper[helperLeft];
helperLeft++;
}
else
{
array[current] = helper[helperRight];
helperRight++;
}
current++;
}
while(helperLeft<=mid)
array[current++] = helper[helperLeft++];
// copy the remaining elements from the left only and not right because right elememts are already there in dest (array) sorted.
}
void mergeSort(vector<int>&array,int low,int high)
{
if(low < high)
{
int mid = (low+high)/2;
mergeSort(array,low,mid);// sort left half
mergeSort(array,mid+1,high);// sort right half
merge(array,low,mid,high);
}
}
void mergeSort(vector<int>& array)
{
mergeSort(array,0,array.size()-1);
}
int main()
{
vector<int> v;
int i =1;
v.push_back(i);
v.push_back(i+6);
v.push_back(i+2);
v.push_back(i+8);
v.push_back(i+3);
v.push_back(i+4);
v.push_back(i+1);
v.push_back(i+5);
v.push_back(i+7);
vector<int>::iterator it=v.begin();
while(it!=v.end())
{
cout<<" "<<*it;
it++;
}
cout<<endl;
mergeSort(v);
it = v.begin();
while(it!=v.end())
{
cout<<" "<<*it;
it++;
}
cout<<endl;
}

Merge sort throwing index out of bounds exception in Xcode

I am trying to implement a simple merge sort for even number of elements using the following code :
#include <iostream>
using namespace std;
void merge(int arr1[10],int len1,int arr2[10],int len2,int arr3[10],int len3)
{
int i,j,k;
while(i<len1&&j<len2&&k<len3)
{
if(arr1[i]<arr2[j])
{
arr3[k] = arr1[i];
i++;k++;
}
else if(arr1[i]>arr2[j])
{
arr3[k] = arr2[j];
k++;
j++;
}
}
}
void mergeSort(int a[10],int n)
{
int arr1[10],arr2[10];
for(int i=0;i<n/2;i++)
{
arr1[i] = a[i];
}
for(int i=(n/2+1);i<n;i++)
{
arr2[i] = a[i];
}
mergeSort(arr1,n/2);
mergeSort(arr2,n/2);
merge(arr1,n/2,arr2,n/2,a,n);
}
int main() {
int arr[10],n;
cout << "Enter number of elements\n";
cin >> n;
cout<<"Enter elements\n";
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
mergeSort(arr, n);
cout<<"Sorted array is"<<endl;
for(int i=0;i<n;i++)
{
cout<<arr[i]<<endl;
}
return 0;
}
But I am getting a EXC_BAD_ACESS error on the opening brace of the mergeSort() method. I am new to Xcode and not sure on how to fix this. How do I fix this ?
Thanks !
You have forgot to initialize the int variables i, j, k to 0 (zero) in the function definition for merge(...).
void merge(int arr1[10],int len1,int arr2[10],int len2,int arr3[10],int len3)
{
// int i,j,k; // Not initialized.
int i = j = k = 0;
while(i<len1&&j<len2&&k<len3)
{
...
...
}
After Edit:
void mergeSort(int a[10],int n)
{
int arr1[10],arr2[10];
for(int i=0;i<n/2;i++)
{
arr1[i] = a[i];
}
// Here you are skipping the middle index.
// Let's say array is of length 10, then arr1 contains elements on index from 0 to 4 (5 elements),
// whereas arr2 contains elements on index from 6 to 9 (4 elements).
// 5th index element is missing.
// for(int i=(n/2+1);i<n;i++)
for(int i=(n/2);i<n;i++)
{
arr2[i] = a[i];
}
mergeSort(arr1,n/2);
mergeSort(arr2,n/2);
merge(arr1,n/2,arr2,n/2,a,n);
}
Hope it helps!

Why does my merge sort implementation return weird numbers?

The following is my code-
#include<iostream>
#include<cstdlib>
using namespace std;
void MergeSort(int*,int,int);
void Merge(int*,int*,int*,int,int,int);
int main()
{
int a[10];
for(int i=0;i<10;i++)
cin>>a[i];
cout<<"The unsorted array is : ";
for(int i=0;i<10;i++)
cout<<a[i]<<" ";
MergeSort(a,0,10);
cout<<"\n\n The Sorted array is : ";
for(int i=0;i<10;i++)
cout<<a[i]<<" ";
return 0;
}
void MergeSort(int *a,int l,int h)
{
int m = (l+h)/2;
int l1 = m-l;
int h1 = h-m;
int *lp = (int*)malloc(l1*sizeof(int));
int *rp = (int*)malloc(h1*sizeof(int));
for(int i=l,j=0;i<m;i++,j++)
{
lp[j] = a[i];
}
for(int i=m,j=0;i<h;i++,j++)
{
rp[j] = a[i];
}
if(l1 != 1)
MergeSort(lp,l,m);
if(h1 != 1)
MergeSort(rp,m,h);
Merge(lp,rp,a,l1,h1,(h-l));
}
void Merge(int *lp,int *rp,int *a,int l1,int h1,int b)
{
int i,j,k;
i=j=k=0;
while(i<l1 && j<h1)
{
if(lp[i] <= rp[j])
{
a[k] = lp[i];
i++;
}
else if(lp[i] > rp[j])
{
a[k] = rp[j];
j++;
}
k++;
}
while(i<l1)
{
a[k] = lp[i];
i++;k++;
}
while(j<h1)
{
a[k] = rp[j];
j++;k++;
}
}
for a given input like 1 5 2 4 3 6 7 9 8 7
output is - 0 0 1 3 5 and then some large numbers like 46977154 etc.
I can't figure out the problem in my code.
I found the error:
MergeSort(rp,m,h)
This should be
MergeSort(rp,l,h-m)
The rest is correct.

Heap Sort in C++

Okay, so after struggling with trying to debug this, I have finally given up. I'm a beginner in C++ & Data Structures and I'm trying to implement Heap Sort in C++. The code that follows gives correct output on positive integers, but seems to fail when I try to enter a few negative integers.
Please point out ANY errors/discrepancies in the following code. Also, any other suggestions/criticism pertaining to the subject will be gladly appreciated.
//Heap Sort
#include <iostream.h>
#include <conio.h>
int a[50],n,hs;
void swap(int &x,int &y)
{
int temp=x;
x=y;
y=temp;
}
void heapify(int x)
{
int left=(2*x);
int right=(2*x)+1;
int large;
if((left<=hs)&&(a[left]>a[x]))
{
large=left;
}
else
{
large=x;
}
if((right<=hs)&&(a[right]>a[large]))
{
large=right;
}
if(x!=large)
{
swap(a[x],a[large]);
heapify(large);
}
}
void BuildMaxHeap()
{
for(int i=n/2;i>0;i--)
{
heapify(i);
}
}
void HeapSort()
{
BuildMaxHeap();
hs=n;
for(int i=hs;i>1;i--)
{
swap(a[1],a[i]);
hs--;
heapify(1);
}
}
void main()
{
int i;
clrscr();
cout<<"Enter length:\t";
cin>>n;
cout<<endl<<"Enter elements:\n";
for(i=1;i<=n;i++) //Read Array
{
cin>>a[i];
}
HeapSort();
cout<<endl<<"Sorted elements:\n";
for(i=1;i<=n;i++) //Print Sorted Array
{
cout<<a[i];
if(i!=n)
{
cout<<"\t";
}
}
getch();
}
I've been reading up on Heap Sort but I'm not able to grasp most of the concept, and without that I'm not quite able to fix the logical error(s) above.
You set hs after calling BuildMaxHeap. Switch those two lines.
hs=n;
BuildMaxHeap();
When I implemented my own heapsort, I had to be extra careful about the indices; if you index from 0, children are 2x+1 and 2x+2, when you index from 1, children are 2x and 2x+1. There were a lot of silent problems because of that. Also, every operation needs a single well-written siftDown function, that is vital.
Open up Wikipedia at the Heapsort and Binary heap articles and try to rewrite it more cleanly, following terminology and notation where possible. Here is my implementation as well, perhaps it can help.
Hmmm now that I checked your code better, are you sure your siftDown/heapify function restricts sifting to the current size of the heap?
Edit: Found the problem! You do not initialize hs to n before calling BuildMaxHeap().
I suspect it's because you're 1-basing the array. There's probably a case where you're accidentally 0-basing it but I can't spot it in the code offhand.
Here's an example if it helps.
#include <iostream>
#include <vector>
using namespace std;
void max_heapify(std::vector<int>& arr, int index, int N) {
// get the left and right index
int left_index = 2*index + 1;
int right_index = 2*index + 2;
int largest = 0;
if (left_index < N && arr[left_index] > arr[index]) {
// the value at the left_index is larger than the
// value at the index of the array
largest = left_index;
} else {
largest = index;
}
if (right_index < N && arr[right_index] > arr[largest]) {
// the value at the right_index is larger than the
// value at the index of the array
largest = right_index;
}
// check if largest is still the index, if not swap
if (index != largest) {
// swap the value at index with value at largest
int temp = arr[largest];
arr[largest] = arr[index];
arr[index] = temp;
// once swap is done, do max_heapify on the index
max_heapify(arr, largest, N);
}
}
void build_max_heap(std::vector<int>& arr, int N) {
// select all the non-leaf except the root and max_heapify them
for (int i = N/2 - 1; i >= 0; --i) {
max_heapify(arr, i, N);
}
}
void heap_sort(std::vector<int>& arr) {
int N = arr.size();
int heap_size = N;
// build the max heap
build_max_heap(arr, N);
// once max heap is built,
// to sort swap the value at root and last index
for (int i = N - 1; i > 0; --i) {
// swap the elements
int root = arr[0];
arr[0] = arr[i];
arr[i] = root;
// remove the last node
--heap_size;
// perform max_heapify on updated heap with the index of the root
max_heapify(arr, 0, heap_size);
}
}
int main() {
std::vector<int> data = {5,1,8,3,4,9,10};
// create max heap from the array
heap_sort(data);
for (int i : data) {
cout << i << " ";
}
return 0;
}
# include <iostream> //Desouky//
using namespace std;
void reheapify(int *arr, int n, int i)
{
int parent = i; // initilaize largest as parent/root
int child1 = 2 * i + 1; // to get first chid
int child2 = 2 * i + 2; // to get second child
if (child1 < n && arr[child1] > arr[parent]) // if child2 > parent
{
parent = child1;
}
//if child > the parent
if (child2 < n && arr[child2] > arr[parent])
{
parent = child2;
}
// if the largest not the parent
if (parent != i)
{
swap(arr[i], arr[parent]);
// Recursively heapify the affected sub-tree
reheapify(arr, n, parent);
}
}
void heapsort(int *arr, int n)
{
// build a heap
for (int i = n - 1; i >= 0; i--)
{
reheapify(arr, n, i);
}
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--)
{
// Move current root to end
swap(arr[0], arr[i]);
// call max heapify on the reduced heap
reheapify(arr, i, 0);
}
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
cin >> n;
int* arr = new int[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
heapsort(arr, n);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
}