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?
Related
void swap(int a[], int x, int y)
{
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
void sort(int arr[], int x)
{
static int count = 0;
if (x == 1)
{
return;
}
int min = 100; // random value
int index;
for (int i = 0; i < x; i++)
{
if (arr[i] < min)
{
min = arr[i];
index = i;
}
}
swap(arr, count, index);
count++;
sort(arr + 1, x - 1);
}
int main()
{
int x;
cin >> x;
int A[x];
for (int i = 0; i < x; i++)
{
cin >> A[i];
}
sort(A, x);
for (int i = 0; i < x; i++)
{
cout << A[i] << " ";
}
cout << endl;
return 0;
}
this code is of selection sort using recursion. It is printing garbage values. what's the mistake in this. i am not sure but i guess because of using the static variable in the sort function(). it is printing garbage values
Replace swap(arr, count, index); with
swap(arr, 0, index);
and remove static int count = 0;.
Replace sort(A, x); in the main with
sort(A, x - 1);
and change the condition if (x == 1) to if (x == 0).
I suggest to rename index to last.
Replace min = 100; with
min = arr[0];
For starters variable length arrays like this
int x;
cin >> x;
int A[x];
is not a standard C++ feature.
Nevertheless the function can invoke undefined behavior when for example is called with the second parameter equal to 0.
Also there is no sense to declare the static variable.
The function will not sort an array elements of which have values greater than 100.
The variable index must be initialized to 0 before the for loop.
Also there is already the standard function std::swap that swaps two objects.
The function can be defined the following way
#include <algorithm>
void selection_sort( int a[], size_t n )
{
if ( not ( n < 2 ) )
{
auto it = std::min_element( a, a + n );
if ( it != a ) std::iter_swap( a, it );
selection_sort( a + 1, n - 1 );
}
}
If you do not know yet standard algorithms then the functions can look the following way
void swap( int &a, int &b )
{
int rmp = a;
a = b;
b = tmp;
}
void selection_sort( int a[], size_t n )
{
if ( not ( n < 2 ) )
{
size_t index = 0;
for ( size_t i = 1; i < n; i++ )
{
if ( a[i] < a[index] ) index = i;
}
if ( index != 0 ) swap( a[0], a[index] );
selection_sort( a + 1, n - 1 );
}
}
One of the easy ways of doing the selection sort using recursion is as follows:
#include<iostream>
using namespace std;
void selectionSort(int *arr, int size,int minIndex){
//base case
if(size ==0 || size ==1 || minIndex == size){
return;
}
//processing
for(int i=minIndex+1;i<size;i++){
if(arr[i]<arr[minIndex]){
swap(arr[minIndex], arr[i]);
}
}
//recursive call
selectionSort(arr,size,minIndex+1);
}
int main(){
int arr[7]={7,6,5,4,3,2,1};
int size = 7;
int minIndex = 0;
selectionSort(arr,size,minIndex);
for(int i=0;i<7;i++){
cout<<arr[i]<<" ";
}
}
We are creating a minIndex at the starting of the array and comparing it with the values in the remaining array, to get the minimum value of the whole array on the left-most side. At each recursive call, we will increment the place of minIndex for further comparison. Hope this helps.
a=[6,5,4,3,2,1,0,-1]
length=a.length
cur=0
n=cur+1
function fun(n)
{
if(cur==length-1)
{
return a
}
else if(a[cur]>a[n])
{
temp=a[cur]
a[cur]=a[n]
a[n]=temp
if(n==length-1)
{
n=cur
cur++
}
// console.log(a)
// console.log(cur)
return fun(n+1)
}
else
{
if(n==length-1)
{
n=cur
cur++
}
return fun(n+1)
}
}
let t=[]
t=[...fun(n)]
console.log(t)
I tried to implement number of inversions in an array, using merge sort.
Every time I execute this code, I get different value of the number of inversions. I am not able to figure out the reason for this. Please have a look at the code and tell me the mistake.
#include<stdio.h>
#include<iostream>
using namespace std;
int count =0;
void merge(int A[],int start,int mid,int end)
{
int size1 = mid-start+1;
int size2 = end-(mid+1)+1;
int P[size1];
int Q[size2];
for(int i=0;i<size1;i++)
P[i]=A[start+i];
for(int j=0;j<size2;j++)
Q[j]=A[mid+j+1];
int k = 0;
int l = 0;
int i =0;
while(k<mid && l<end)
{
if(P[k]>Q[l])
{
A[i] = Q[l];
l++; i++;
count++;
}
else
{
A[i] = P[k];
k++; i++;
}
}
}
void inversions(int A[],int start,int end)
{
if(start!=end)
{
int mid = (start+end)/2;
inversions(A,start,mid);
inversions(A,mid+1,end);
merge(A,start,mid,end);
}
}
int main()
{
int arr[] = {4,3,1,2,7,5,8};
int n = (sizeof(arr) / sizeof(int));
inversions(arr,0,n-1);
cout<<"The number of inversions is:: "<<count<<endl;
return 0;
}
int k = 0;
int l = 0;
int i =0;
while(k<mid && l<end)
{
if(P[k]>Q[l])
{
A[i] = Q[l];
l++; i++;
count++;
}
else
{
A[i] = P[k];
k++; i++;
}
}
Few mistakes here, i starts from start and not 0. k must loop from 0 till size1 and not till mid. Similarly, l must loop from 0 till size2 and not till end. You are incrementing count by 1 when P[k] > Q[l] but this is incorrect. Notice that all the elements in array P following the element P[k] are greater than Q[l]. Hence they also will form an inverted pair. So you should increment count by size1-k.
Also, the merge procedure should not only count the inversions but also merge the two sorted sequences P and Q into A. The first while loop while(k<size1 && l<size2) will break when either k equals size1 or when l equals size2. Therefore you must make sure to copy the rest of the other sequence as it is back into A.
I have made the appropriate changes in merge and pasted it below.
void merge(int A[],int start,int mid,int end)
{
int size1 = mid-start+1;
int size2 = end-(mid+1)+1;
int P[size1];
int Q[size2];
for(int i=0;i<size1;i++)
P[i]=A[start+i];
for(int j=0;j<size2;j++)
Q[j]=A[mid+j+1];
int k = 0;
int l = 0;
int i = start;
while(k<size1 && l<size2)
{
if(P[k]>Q[l])
{
A[i] = Q[l];
l++; i++;
count += size1-k;
}
else
{
A[i] = P[k];
k++; i++;
}
}
while (k < size1)
{
A[i] = P[k];
++i, ++k;
}
while (l < size2)
{
A[i] = Q[l];
++i, ++l;
}
}
int P[size1];
int Q[size2];
VLA (Variable length arrays) are not supported by C++. size1 and size2 are unknown during compile time. So, each time they get a different value and hence the difference in output.
Use std::vector instead
std::vector<int> P(size1, 0); //initialize with size1 size
std::vector<int> Q(size2, 0); //initialize with size2 size
#include<iostream>
using namespace std;
int heapSize;
void maxHeapify(int a[],int n,int i)
{
int l=2*i+1;
int r=2*i+2;
int largest=i;
if(l<heapSize&&a[l]>a[i]) largest=l;
if(r<heapSize&&a[r]>a[i]) largest=r;
if(largest!=i)
{
swap(a[i],a[largest]);
maxHeapify(a,n,largest);
}
}
void heapSort(int a[],int n)
{
heapSize=n;
for(int i=n/2;i>=0;i--)maxHeapify(a,n,i);
for(int i=n-1;i>=1;i--)
{
swap(a[0],a[i]);
heapSize--;
maxHeapify(a,n,0);
}
}
int main()
{
int a[]={1,2,3,7,9,15,13,11};
heapSort(a,8);
for(int i=0;i<8;i++)cout<<a[i]<<" ";
return 0;
}
output:1 2 7 11 15 3 9 13
I want to achieve a heap sort,but something went wrong,i have tried to debug it for hours,i can't find any more bugs,maybe something wrong with the logic as well as can't figure out what's wrong with my code, which doesn't output right order.
In your maxHeapify fucntion you missed to compare your heap's right child with current largest. Your function will be
void maxHeapify(int a[], int n, int i) {
int l = 2 * i + 1;
int r = 2 * i + 2;
int largest = i;
if(l < heapSize && a[l] > a[i]) largest = l;
if(r < heapSize && a[r] > a[largest]) largest = r;
if(largest! = i)
{
swap(a[i], a[largest]);
maxHeapify(a, n, largest);
}
}
There are several questions related to this error on stackoverflow, and I understand that its related to excess memory usage by the array, or when using pointers (I tried this with vectors aswell) but using a small array, it still shows this error. The same code earlier was running fine (for merge sorting an array).
My input was as follows:
5
9 8 1 2 4
Output:
Segmentation fault: 11
#include<iostream>
#include<vector>
using namespace std;
void merge(vector <int> ar, int l, int m, int r){
int n1 = m-l+1;
int n2 = r-m;
int L[n1];
int R[n2];
for (int i = 0; i < n1; ++i)
{
L[i]=ar[l+i];
}
for (int j = 0; j < n2; ++j)
{
R[j]=ar[m+j+1];
}
int i,j;
i = j = 0;
int k = i;
while(i<n1 && j<n2){
if (L[i]<R[j])
{
ar[k]=L[i];
i++;
}
else if (R[j]<L[i])
{
ar[k]=R[j];
j++;
}
k++;
}
while(i<n1){
ar[k]=L[i];
i++;
k++;
}
while(j<n2){
ar[k]=R[j];
j++;
k++;
}
}
void mergesort(vector <int> ar, int l, int r){
int m;
m=r+(l-r)/2;
if (l<r)
{
mergesort(ar, l, m);
mergesort(ar, m+1, r);
merge(ar, l, m, r);
}
}
void print(vector <int> ar, int size){
for (int i = 0; i < size; ++i)
{
cout<<ar[i]<< " ";
}
}
int main()
{
int n;
cin>>n;
vector <int> ar;
for (int i = 0; i < n; ++i)
{
cin>>ar[i];
}
print(ar,n);
mergesort(ar, 0, n-1);
print(ar, n);
return 0;
}
The problem is in part with m=r+(l-r)/2. When l is 0 and r is 1, (l-r)/2 is 0. This makes m equal to 1, l equal to 0, and r equal to 1 and the mergesort(ar, l, m); call identical to the one it just worked through. The stack grows unbounded until you have a segmentation fault. One way to fix this which will also make your code more efficient is to merge the lists when the difference between l and r is below some threshold. Or, you can just swap the two elements when you get to the point where l and r differ by one, like so:
if (l - r <= 1) {
int temp = ar[l];
ar[l] = ar[r];
ar[r] = temp;
return;
}
So, I am writing a code which creates an array with an elements and amount of elements written by user and then a code generates a biggest value which last digit is zero. So, I have accomplished a step of writing an array which is elements entered by user. The hardest part( for me) is to complete a code which generates biggest value which last digit is zero. So yeah, I need an advice in completing this code. Thank you.
for example :
An array - 2 20 25 300 55555
The biggest number which last digit is zero is 300
So yeah, I need an advice in completing this code. Here is a code what I have done so far :
#include "stdafx.h"
#include <stdlib.h>
#include <windows.h>
#include <time.h>
int GetAmount() {
int howmany;
printf("Enter amount of elements - ");
scanf_s("%i", &howmany);
return howmany;
}
void GetArray(int a[], int n) {
printf("Enter elements - \n");
for (int i = 0; i < n; i++)
{ printf("%i ->", i);
scanf_s("%i", &a[i]);
}
}
int LastDigitZero(int n[], int a) {
for (int i = 0; i < a; i++)
{
if (n[i] % 10 == 0) {
return 0;
}
}
}
int maxvalue(int a[], int n) {
int temp = 0;
for (int i = 0; i < n; i++)
{
if (a[i] > temp) {
temp = a[i];
}
}
return temp;
}
void main() {
int amount = GetAmount();
int array[100];
GetArray(array, amount);
int max = maxvalue(array, amount);
printf("Max Value is %i\n", max);
}
Thank you for your attention, have a nice day! :)
It works! That's how it looks!
#include "stdafx.h"
#include <stdlib.h>
#include <windows.h>
#include <time.h>
int GetAmount() {
int howmany;
printf("Enter amount of elements - ");
scanf_s("%i", &howmany);
return howmany;
}
void GetArray(int a[], int n) {
printf("Enter elements - \n");
for (int i = 0; i < n; i++)
{ printf("%i ->", i);
scanf_s("%i", &a[i]);
}
}
int maxvalue(int a[], int n) {
int temp = 0;
for (int i = 0; i < n; i++)
{
if (a[i] % 10 == 0 && a[i] > temp) {
temp = a[i];
}
}
return temp;
}
void main() {
int amount = GetAmount();
int array[100];
GetArray(array, amount);
int max = maxvalue(array, amount);
printf("The biggest number which last digit is zero is %i\n ", max);
system("pause");
}
Thank you guys for the answers! That was fast!!! :)
You almost have it. First any number that ends in 0 mod 10 is 0 so that is how you can check if the last digit is 0. With that you would change maxvalue() to
int maxvalue(int a[], int n) {
int temp = a[0];
for (int i = 1; i < n; i++)
{
if (a[i] % 10 == 0 && a[i] > temp) {
temp = a[i];
}
}
return temp;
}
I also made a change to set temp to the value of a[0] as if your array is all negative numbers then 0 would be the largest number. Since temp is already a[0] we can then start the for loop at 1.
You should check if there is a solution, in this example you could check that the value returned by maxValue finishes by 0 (if none of the values finishes by 0 then it would return a[0]):
int maxValue(int a[], int n) {
int temp= a[0]
for (int i(1); i<n;i++) {
if (a[i] % 10 == 0 && (temp % 10 != 0 || a[i] > temp )) temp = a[i];
}
return temp;
}