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] << " ";
}
}
Related
I am new to coding and I am unable to see what is wrong with this Logic.
I am unable to get the desired output for this program.
The Question is to find the minimum and maximum elements of an array.
The idea is to create two functions for minimum and maximum respectively and have a linear search to identify the maximum as well as a minimum number.
#include <iostream>
#include<climits>
using namespace std;
void maxElement(int a[], int b)
{
// int temp;
int maxNum = INT_MIN;
for (int i = 0; i < b; i++)
{
if (a[i] > a[i + 1])
{
maxNum = max(maxNum, a[i]);
}
else
{
maxNum = max(maxNum, a[i+1]);
}
// maxNum = max(maxNum, temp);
}
// return maxNum;
cout<<maxNum<<endl;
}
void minElement(int c[], int d)
{
// int temp;
int minNum = INT_MAX;
for (int i = 0; i < d; i++)
{
if (c[i] > c[i + 1])
{
minNum = min(minNum,c[i+1]);
}
else
{
minNum = min(minNum,c[i]);
}
// minNum = min(minNum, temp);
}
// return minNum;
cout<<minNum<<endl;
}
int main()
{
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
minElement(arr,n);
maxElement(arr,n);
return 0;
}
You are already comparing each element to the current max / min. It is not clear why in addition you compare to adjacent elements. Trying to access a[i+1] in the last iteration goes out of bounds of the array and causes undefined behavior. Just remove that part:
void maxElement(int a[], int b)
{
// int temp;
int maxNum = INT_MIN;
for (int i = 0; i < b; i++)
{
maxNum = max(maxNum, a[i]);
}
cout<<maxNum<<endl;
}
Similar for the other method.
Note that
int n;
cin >> n;
int arr[n];
is not standard C++. Variable length arrays are supported by some compilers as an extension, but you don't need them. You should be using std::vector, and if you want to use c-arrays for practice, dynamically allocate the array:
int n;
cin >> n;
int* arr = new int[n];
Also consider to take a look at std::minmax_element, which is the standard algorithm to be used when you want to find the min and max element of a container.
Last but not least you should seperate computation from output on the screen. Considering all this, your code could look like this:
#include <iostream>
#include <algorithm>
std::pair<int,int> minmaxElement(const std::vector<int>& v) {
auto iterators = std::minmax_element(v.begin(),v.end());
return {*iterators.first,*iterators.second};
}
int main()
{
int n;
std::cin >> n;
std::vector<int> input(n);
for (int i = 0; i < n; i++)
{
std::cin >> input[i];
}
auto minmax = minmaxElement(input);
std::cout << minmax.first << " " << minmax.second;
}
The method merely wraps the standard algorithm. It isnt really needed, but I tried to keep some of your codes structure. std::minmax_element returns a std::pair of iterators that need to be dereferenced to get the elements. The method assumes that input has at least one element, otherwise dereferencing the iterators is invalid.
I'm a beginner so please excuse me if it is a dumb question.
I am trying to code a heap sort that takes input from user in an array and heap sorts it but i can not find a way to implement user input array in my code.
at the end, in the main function, i have to use array arr[]={} but i either have to define the elements or the number of elements so it creates zeros if i define the array as arr[10]={}
here is the code :
// Heap Sort in C++
#include <iostream>
using namespace std;
void heapify(int arr[], int n, int i) {
// Find largest among root, left child and right child
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest])
largest = left;
if (right < n && arr[right] > arr[largest])
largest = right;
// Swap and continue heapifying if root is not largest
if (largest != i) {
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
// main function to do heap sort
void heapSort(int arr[], int n) {
// Build max heap
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
// Heap sort
for (int i = n - 1; i >= 0; i--) {
swap(arr[0], arr[i]);
// Heapify root element to get highest element at root again
heapify(arr, i, 0);
}
}
// Print an array
void printArray(int arr[], int n) {
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
cout << "\n";
}
// Driver code
int main() {
int arr[10] = { };
cout << "Enter the numbers : " << endl;
for (int x = 1; x <= 5; x++)
{
cin >> arr[x];
}
int n = sizeof(arr) / sizeof(arr[0]);
heapSort(arr, n);
cout << "Sorted array is \n";
printArray(arr, n);
}
here is the output :
code output image
You can consider std::vector and pass it by reference to your heapify(...) to save memory.
I wrote the code with o(n^2) complexity.I could not find the error.My idea was to first sort the array and then starting from the first element if the second next is equal increment i by 2 and when the if condition is not fulfilled the element is found Can someone please help me this.
Thanks in advance
#include<iostream>
using namespace std;
int main()
{
int arr[100];
int n,i,j,temp;
cin>>n;
for(i=0;i<n;i++)
{
cin>>arr[i];
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(arr[i]>arr[j])
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
i=0;
for(j=i+1;j<n;j++)
{
if(arr[i] == arr[j])
{
i=i+2;
}
}
cout<<arr[i];
return 0;
}
To find a non-repetitive element in an array the first thing that comes to mind is that if we first sort the array and then try to manipulate it. The sorting process is easy and as follows:
int arr[] = {/*Some array*/};
int arrSize = sizeof(arr)/sizeof(int);
//Lets sort the array
for(int i=0;i<arrSize;i++)
{
for(int j=i;j<arrSize;j++)
{
if(arr[i]>arr[j])
{
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
}
After sorting the array we may see different scenarios like:
int arr1[] = {1,1,2,2,3};
int arr2[] = {1,2,2,3,3};
int arr3[] = {1,1,2,3,3};
We have to design an algorithm such that it can differentiate and easily manipulate the three scenarios. Let n be our number. The first scenario is to check if the last isn't the same as the previous one by:
if(arr[arrSize-1] != arr[arrSize-2]) //The last is not the same as the previous
{
n=arr[arrSize-1];
}
The second one is similar to the first:
if(arr[0] != arr[1]) // The first element is not the same as the second
{
n = arr[0];
}
The third one is easy too, we just have to check if two neighbors are never equal to the middle number, this is as follows:
for(int i=1;i<arrSize-1;i++)
{
if(arr[i-1] != arr[i] && arr[i] != arr[i+1])
{
n=arr[i];
break;
}
}
And so the full code would become:
#include <iostream>
using namespace std;
int main()
{
int arr[] = {1,2,3,4,2,3,1};
int arrSize = sizeof(arr)/sizeof(int);
//Lets sort the array
for(int i=0;i<arrSize;i++)
{
for(int j=i;j<arrSize;j++)
{
if(arr[i]>arr[j])
{
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
}
int n;
if(arr[0] != arr[1]) // The first element is not the same as the second
{
n = arr[0];
}
else if(arr[arrSize-1] != arr[arrSize-2]) //The last is not the same as the previous
{
n=arr[arrSize-1];
}
else //Lets search for a number such that its not the same as the numbers on the left and on the right
{
for(int i=1;i<arrSize-1;i++)
{
if(arr[i-1] != arr[i] && arr[i] != arr[i+1])
{
n=arr[i];
break;
}
}
}
cout << n;
}
The Second Way (Better one).
Here's another way we could solve this problem. Suppose that I have a number n=3, if i XORed it with 3 i will get 0, so if we have an array lets say arr[] = {1,2,1}, I first assign n=0, then XOR it with the firs element (1), next I XOR n with the second element and then with the third element. What will happen? The third XOR will cancel the effect of the first thus n will equal to 1. Sample Code:
#include <iostream>
using namespace std;
int main()
{
int arr[] = {1,2,3,4,2,3,1};
int arrSize = sizeof(arr)/sizeof(int);
int n=0;
for(int i=0;i<arrSize;i++)
{
n^=arr[i];
}
cout << n;
}
This code is O(n).
Use XOR. XOR of all array elements gives us the number with a single occurrence.
#include <bits/stdc++.h>
using namespace std;
int singleoccurence(int arr[], int n)
{
int res = arr[0];
for (int i = 1; i < n; i++)
{
res = res ^ arr[i];
}
return res;
}
int main()
{
int arr[] = {7, 3, 5, 4, 5, 3, 4};
int n = sizeof(arr) / sizeof(arr[0]);
int val = singleoccurence(arr, n);
cout << "ELEMENT OCCURING ONLY ONCE IS :" << val;
}
Solution in C#
public static int lonelyinteger(List<int> a)
{
int lonely = 0;
foreach(var item in a)
{
List<int> listTemp = a.Where(x => x == item).ToList();
if(listTemp.Count == 1)
lonely = listTemp.FirstOrDefault();
}
return lonely;
}
I'm trying to create a program merge-sort on an array of int butI keep having troubles running this merge sort, it gives me a segment fault but I couldn't find anything wrong with it. In void mergesort when I put first <= last then the segment fault appears if not, then 5 5 5 5 is being print.
#include <iostream>
using namespace std;
void merge(int *arr, int size, int first, int middle, int last)
{
int temp[size];
for(int i = first; i<=last; i++)
{
temp[i] = arr[i];
}
int i=first, j=middle+1, k=0;
while(i<=middle && j<=last)
{
if(temp[i] <= temp[j])
{
arr[k] = temp[i];
i++;
}
else
{
arr[k]=temp[i];
j++;
}
k++;
}
while(i<=middle)
{
arr[k]=temp[i];
k++;
i++;
}
}
void mergesort(int *arr, int size, int first, int last)
{
if(first<last)
{
int middle = ( first + last )/2;
mergesort(arr,size,first,middle);
mergesort(arr,size,middle+1,last);
merge(arr,size,first,middle,last);
}
}
int main()
{
cout <<"Him";
const int size = 10;
int numbers [] = {5,10,1,6,2,9,3,8,7,4};
mergesort(numbers,size,0,9);
for( int i= 0; i<size; ++i)
{
cout << numbers[i] << " ";
}
return 0;
}
There are (at least) two bugs. This:
else
{
arr[k]=temp[i];
j++;
}
should be this:
else
{
arr[k]=temp[j];
j++;
}
and this:
int i=first, j=middle+1, k=0;
should be this:
int i=first, j=middle+1, k=first;
In general, you ought to learn to step through the code, at least by putting diagnostic output statements here and there. Once you have the hang of that you can move up to a good debugger.
The standard library already implements a function that merges correctly: std::inplace_merge. Implementation adapted from this more general post
void mergesort(int * first, int * last)
{
std::ptrdiff_t N = std::distance(first, last);
if (N <= 1) return;
int * middle = std::next(first, N / 2);
mergesort(first, middle);
mergesort(middle, last);
std::inplace_merge(first, middle, last);
}
int main()
{
cout <<"Him";
const int size = 10;
int numbers [] = {5,10,1,6,2,9,3,8,7,4};
mergesort(numbers, numbers+size);
for( int i= 0; i<size; ++i)
{
cout << numbers[i] << " ";
}
return 0;
}
Suggestion 1:
Instead of that line:
int temp[size];
If you need a dynamic size array use:
int temp = new int[size];
Then once you are done with it
delete[] temp;
Edit: As Neil suggested using std::vector is may be more useful than arrays in such situations (if you are allowed to use it).
Your code has 3 bugs, Also you can reduce your code length too if required.
void merge(int *arr, int size, int first, int middle, int last)
{
int temp[size];
for(int i = first; i<=last; i++)
temp[i] = arr[i];
int i=first, j=middle+1, k=first; // 1st Change, Set k to first instead of 0
while(i<=middle && j<=last)
{
if(temp[i] <= temp[j])
arr[k++] = temp[i++];
else
arr[k++]=temp[j++]; // 2nd Change, use j instead of i
}
while(i<=middle)
arr[k++]=temp[i++];
while(j<=last) // 3rd Change you missed this case
arr[k++]=temp[j++];
}
Live Code
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!