Quick sort implementation in c++ - c++

I have pasted my implementation of the quicksort algorithm below. After some debugging I figured out that the recursion of the function quicksort() does not seem to terminate. But it seems to me that my algorithm is fine and I am not able to fix the bug.
/*
quicksort
*/
int a[20];
int partition(int left,int right, int*a)
{
//chose some pivot element- in this case i choose the middle one
int pivot=(left+right)/2;
int b[10],c[10],i=left,j=0;
int k=0;
int pivot_element=a[pivot];
//b is the left side ,c is the right side
while(i<=right)
{
if(a[i]!=pivot_element)
{
if(a[i]<a[pivot])
{
b[j++]=a[i];
}
else
{
c[k++]=a[i];
}
}
i++;
}
//combine
i=left;
for(int q=0;q<j;q++)
a[i++]=b[q];
a[i++]=pivot_element;
for(int p=0;p<k;p++)
a[i++]=c[p];
return j; //return the new position of the pivot
}
void quicksort(int left,int right,int *a)
{
int index=partition(left,right,a);
if(index-left>0)
quicksort(left,index,a);
if(right-index+1>0)
quicksort(index+1,right,a);
}
int main()
{
int size;
cin>>size;
for(int i=0;i<size;i++)
cin>>a[i];
quicksort(0,size-1,a);
for(int i=0;i<size;i++)
cout<<a[i]<<" ";
return 0;
}**

In your partition function, this:
return j;
should be this:
return left+j;
You could have detected this bug by testing the function, before writing other code that called it.

Your recursion lacks a stop criteria.

Related

Quick sort: Pivot is the first element that is greater than its neighbor

I am learning quick sort and I found an algorithm where pivot is the first element that is greater than its neighbor, here is pseudo code
void quicksort(int i,int j)
{
pivotindex=findpivot(i,j);
if(pivotindex!=-1)
{
pivot=a[pivotindex];
k=partition(i,j,pivot); // l
quicksort(i,k-1);
quicksort(k,j);
}
}
int findpivot(int i, int j)
{
for i=0 to j
{
if(a[i]>a[i+1])
return(i);
else if(a[i]<a[i+1])
return(i+1);
else
continue;
}
return(-1);
}
int partition(int i, int j, int pivot)
{
int l, r;
l=i, r=j;
do
{
swap(a[l],a[r]);
while(a[l]<pivot)
l=l+1;
while(a[r]>=pivot)
r=r-1;
} while(l<r);
return(l);
}
Will this pseudocode work fine?
I tried to write c++ code for this, here is my code
#include <iostream>
using namespace std;
void swap(int *i,int *j){
int temp = *i;
*i = *j;
*j = temp;
}
int partition(int l, int r, int idx, int arr[]){
do{
int index = arr[idx];
swap(&arr[l],&arr[r]);
//cout<<arr[l]<<" "<<arr[r]<<" pivot : "<<index<<endl;
while(arr[l]<index){
l=l+1;
}
while(arr[r]>=index){
r=r-1;
}
}while(l<r);
return l;
}
int findpivot(int l,int r,int arr[]){
for(int i = l; i<=r; i++){
if(arr[i]>arr[i+1]){
return i;
}
else if(arr[i+1]>arr[i]){
return i+1;
}
else{
continue;
}
}
return(-1);
}
void Quicksort(int l, int r,int arr[]){
int idx = findpivot(l,r,arr);
if(idx!=-1){
int pivot = arr[idx];
int k = partition(l,r,idx,arr);
Quicksort(l,k-1,arr);
Quicksort(k,r,arr);
}
}
int main()
{
int arr[10] = {19,23,11,43,24,68,98,47,99,89};
Quicksort(0,9,arr);
cout<<"final"<<endl;
for(int i =0;i<10;i++){
cout<<arr[i]<<" ";
}
return 0;
}
My code does fine till these steps and then it turns into an infinite loop, is something wrong with my code, or is the pseudocode wrong?
{89,23,11,43,24,68,98,47,99,19}
{19,23,11,43,24,68,98,47,99,89}
{19,11,23,43,24,68,98,47,99,89}
{11,19}
can someone help me with this.
In addition to what #stark says in a comment about the initial value in the pseudocode's iteration in findpivot, the termination condition is clearly incorrect. Your implementation fixes the initial value (which was probably a typo) but repeats the problem with the termination: for(int i = l; i<=r; i++).
But the termination condition must be i < r. If i is equal to r, the loop will access element a[r+1], which is outside the range (and possibly outside the array). In addition, the algorithm depends on findpivot detecting the end-of-recursion condition, which is when all the elements in the range are equal, not when all the elements in the range and the next element are equal. Hence the endless loop.

The value of the array size variable changes without me expicitly changing it in my c++ merge sort code

The value of the size variable changes to 32760 without me explicitly changing it in my C++ Merge Sort code.
I have shared my code below. The size value is 3 before calling merge sort function but it becomes 32760 after merge sort gets completed.
# include<iostream>
using namespace std;
void printarr(int *arr,int size);
void merge(int *arr,int l,int m,int r)
{
int temp[100];
int k=0,i=l,j=m+1;
while(i<=m && j<=r)
{
if(arr[i]<arr[j])
{
temp[k++]=arr[i++];
}
else
temp[k++]=arr[j++];
}
while(i<=m)
{
temp[k++]=arr[i++];
}
while(j<=r)
{
temp[k++]=arr[j++];
}
for(i=0;i<=k;i++)
{
arr[l+i]=temp[i];
}
}
void mergeSort(int *arr,int l,int r)
{
if(l>=r)
{
return;
}
int m = (l+r)/2;
mergeSort(arr,l,m);
cout<<"left part sorted: \n";
mergeSort(arr,m+1,r);
cout<<"right part sorted: \n";
merge(arr,l,m,r);
}
void printarr(int *arr,int size)
{
cout<<"\nsize in printarr"<<size<<"\n";
/*for(int i=0;i<size;i++)
{
cout<<"arr element "<<i<<" is "<<arr[i]<<"\n";
}*/
}
int main()
{
int arr[]={43,2,3};
int size=sizeof(arr)/sizeof(arr[0]);
cout<<"size is "<<size<<"\n";
mergeSort(arr,0,size-1);
cout<<"\nmerge sort complete\n";
cout<<"\n size in main "<<size<<"\n";
printarr(arr,size);
}
As Adrian suggested, replacing for (i = 0; i <= k; i++) with for (i = 0; i < k; i++) rectifies the error. The k++ in while(i<=m) and while(j<=r) makes the value of k equal to the size of the temp array. Hence, while copying elements of temp array to arr array i<size_of_temp i.e i<k should be used.

What is the error in this bubble sort code?

I wrote this simple code for bubble sort but it gives some random garbage values as output. Can someone please tell me my mistake. I tried to print the output of A[i] and A[j] in the function bubbleSort and looks like it is working fine. But why is the printSortedArray not giving the correct output? Thanks!
#include <iostream>
using namespace std;
void swap(int *a, int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void printSortedArray(int A[],int size)
{
cout<<"the sorted array is"<<endl;
int i;
for(i=0;i<size;i++);
{
cout<<A[i]<<" ";
}
}
void bubbleSort(int A[],int size)
{
int i,j;
for(i=0;i<size;i++)
{
for(j=0;j<size-1-i;j++)
{
if(A[j]>A[j+1])
{
swap(A[j],A[j+1]);
}
}
}
}
int main()
{
int A[50]; int size,i;
cout<<"enter the size of the array: ";
cin>>size;
cout<<"Enter the "<<size<<" numbers to be sorted"<<endl;
for(i=0;i<size;i++)
{
cin>>A[i];
}
bubbleSort(A,size);
printSortedArray(A,size);
return 0;
}
for(i=0;i<size;i++);
The trailing semicolon does not belong there. This results in undefined behavior.
The end result is that this function printed one garbage value after the end of the array.

Need to devise a recursive algorithm for the following problem in c++

A recursive algorithm that gets an integer n and integer array A as input and check if the given array
A contains two integers, such that n= A[i]+A[j] where A[i] & A[j] can be at any position in array.
This is what I have come up with
#include <iostream>
using namespace std;
void func(int arr[],int size,int n)
{
if (size==1)
return;
else
{
for (int i=0;i<n;i++)
for (int j=i+1;j<n;j++)
if (arr[i]+arr[j]==n)
{
cout<<"yes";
return;
}
func(arr,size-1,n);
}
}
int main()
{
int A[] = {1,2,3,4,5};
int n = 8;
func(A,5,n);
return 0;
}
I know it's using recursion but I want a recursive function that avoids all unnecessary iterations. Any help will be greatly appreciated!!
#include <iostream>
using namespace std;
void func(int arr[],int index,int size,int n)
{
if(index==size-1)
return;
int flag=0;
for (int j=index+1;j<size;j++)
if (arr[index]+arr[j]==n)
{
flag=1;
cout<<"yes";
}
if(flag==0)
func(arr,index+1,size,n);
}
int main()
{
int A[] = {1,2,3,4,5};
int n = 6;
func(A,0,5,n);
return 0;
}
If you really want a recursive code, this may be one kind of implementation. All i have done is start from 0th index and sum it with every other element and compare it with with 'n'. If it matches fine otherwise make a recursive call with next index(prev index + 1).

Segmentation Fault Before function is even called

When I try executing this code, the code crashes before the cout statement in print_array even executes. I have no clue why !
However, if I comment out the call to mergesort in the main function, the print_array executes fine.
#include<iostream>
using namespace std;
void print_array( int A[], int n)
{
int i;
cout<<"\n Array elts:\t";
for(i=0;i<n;i++) cout<<A[i]<<" ";
}
void mergesort(int A[], int beg, int end)
{
if(beg>end) return;
mergesort(A,beg,(beg+end)/2);
mergesort(A, ((beg+end)/2)+1, end);
int B[end-beg+1],i,j,k;
i=beg; j=(beg+end)/2;
k=0;
while(i<(beg+end)/2 && j<end)
{
if(A[i] < A[j]) B[k++]=A[i++];
else B[k++]=A[j++];
}
while(i<(beg+end)/2) B[k++]=A[i++];
while(j<end) B[k++]=A[j++];
for(i=beg; i<end; i++) A[i]=B[i];
}
int main()
{
int n=10;
int A[]={1,23,34,4,56,60,71,8,99,0};
print_array(A,n);
mergesort(A,0,n);
print_array(A,n);
}
Update:
Using endl will flush the output and the print_array values will get displayed on the screen. Apart from this, the reason I got a seg fault was because I had not included the equality check in mergesort. Here is the updated code:
#include<iostream>
using namespace std;
void print_array( int A[], int n)
{
int i;
cout<<"\n Array elts:\t";
for(i=0;i<n;i++) cout<<A[i]<<" ";
}
void mergesort(int A[], int beg, int end)
{
if(beg>=end) return;
mergesort(A,beg,(beg+end)/2);
mergesort(A, ((beg+end)/2)+1, end);
int B[end-beg+1],i,j,k;
i=beg; j=(beg+end)/2;
k=0;
while(i<(beg+end)/2 && j<end)
{
if(A[i] < A[j]) B[k++]=A[i++];
else B[k++]=A[j++];
}
while(i<(beg+end)/2) B[k++]=A[i++];
while(j<end) B[k++]=A[j++];
for(i=beg; i<end; i++) A[i]=B[i];
}
int main()
{
int n=10;
int A[]={1,23,34,4,56,60,71,8,99,0};
print_array(A,n);
mergesort(A,0,n);
print_array(A,n);
}
The code is by no means doing what it should but it isn't giving seg faults anymore.
Thanks guys !
Look at the last line in mergesort: You're accessing elements in B from beg to end, but B is zero indexed. That's one problem; there may be more.
My first though is that this is a Stack Corruption which is leading to a "Stack Overflow" when you call other methods. Try getting additional information in GDB, try compiling increasing the debugging level and turning off the optimizations of gcc (i.e., -g3 -O0).
Moreover, you can use the "valgrind" software to find the corruption and post the results here. (Sorry for requesting this here, but I cannot make comments).