recursive quicksort, count swap and comparison issue - c

I want to compare how many swaps and comparisons (<, >, ==, !=) it took for a bubblesort vs. quicksort function to sort an array of unique numbers. The problem is that the quicksort function I use is recursive and I am a bit unsure how to keep track of swaps comparisons. Tried to use pointers to keep track of the count but was unsuccessful. Could anyone help me?
my bubblesort:
void bubble_sort(int arr[], int max)
{
int i=0, j, temp, flag;
int swap=0, comp=0;
while(1)
{
flag = 0;
for (j = 0 && comp++; j < max - i - 1; j++)
{
comp++;
if (arr[j] > arr[j+1])
{
swap++;
/* Swapping */
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag=1;
}
}
i++;
comp++;
if (flag == 0)
{
printf("number of swaps: %d\n",swap);
printf("number of comparisons: %d \n\n",comp);
break;
}
}
}
my quicksort:
void quicksort(int arr[],int first,int last)
{
int pivot,j,temp,i;
if(first<last)
{
pivot=first;
i=first;
j=last;
while(i<j)
{
while(arr[i]<=arr[pivot]&&i<last)
i++;
while(arr[j]>arr[pivot])
j--;
if(i<j)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
temp=arr[pivot];
arr[pivot]=arr[j];
arr[j]=temp;
quicksort(arr,first,j-1);
quicksort(arr,j+1,last);
}
}
solution:
void quick_sort(int arr[],int first,int last, int *swap, int *comp)
{
int pivot,j,temp,i;
if(++(*comp) && first<last)
{
pivot=first;
i=first;
j=last;
while(++(*comp) && i<j)
{
while(++(*comp) && arr[i]<=arr[pivot]&&i<last)
i++;
while(++(*comp) && arr[j]>arr[pivot])
j--;
if(++(*comp) && i<j)
{
++(*swap);
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
++(*swap);
temp=arr[pivot];
arr[pivot]=arr[j];
arr[j]=temp;
quick_sort(arr,first,j-1, swap, comp);
quick_sort(arr,j+1,last, swap, comp);
}
}

Either use a global variable as suggested in the comments :
int _SwapCount = 0;
void quicksort(int arr[],int first,int last)
{
...
//whenever you swap
_SwapCount++;
or take a pointer to an int as a parameter:
void quicksort(int arr[],int first,int last, int* swapCount)
{
...
//whenever you swap
(*swapCount)++;
//recursion
quicksort(arr,first,j-1, swapCount);
...
and output the swapCount once the top level quicksort has completed.
Edit : initially mis-read the tag as c#;

Related

Merge sort not printing sorted array

My code here gets terminated after printing the unsorted array and also gives runtime error on ideone , i am unable to find the error in it . code works fine until the first mergesort in function but gets terminated afterwards without executing merge function . I have tried changing array size but nothing has worked so far . Any help would be appreciated.
#include<stdio.h>
#include<math.h>
void Merge(int arr[],int,int,int,int);
void printArray(int *arr,int n)
{
for (int i = 0; i < n; i++)
{
printf("%d",arr[i]);
printf(" ");
}
printf("\n");
}
void MergeSort(int arr[],int low,int high)
{
int mid;
if(low<high)
{
mid = ceil((low+high)/2);
MergeSort(arr,low,mid-1);
MergeSort(arr,mid,high);
Merge(arr,low,mid-1,mid,high);
}
}
void Merge(int arr[],int low,int mid1,int mid2, int high)
{
int i,c,j;
c = low;
i = low;
j = mid2;
int Temp[high-low+1];
while(i <= mid1 && j<= high)
{
if(arr[i]<arr[j])
{
Temp[c] = arr[i];
i++;
c++;
}
else
{
Temp[c] = arr[j];
j++;
c++;
}
}
while(i<=mid1)
{
Temp[c] = arr[i];
i++;
c++;
}
while(j<=high)
{
Temp[c] = arr[j];
j++;
c++;
}
for(int k=0;k<=high;k++)
{
arr[k] = Temp[k];
}
}
int main(void)
{
int arr[] = {3,5,2,13,12,3,2,13,45};
int n = sizeof(arr)/sizeof(arr[0]);
printf("unsorted array: \n");
printArray(arr,n);
MergeSort(arr,0,n-1);
printf("sorted array: \n");
printArray(arr,n);
return 0;
}
There are several issues:
ceil is not useful as / will perform an integer division and so has already rounded down
Related to this, you should not use mid-1 and mid as arguments in the next recursive calls, but mid and mid+1. The same should be done with the arguments to Merge.
The way you access Temp is wrong. You allocate entries from 0 to high-low, but start your access with a value of c that is low. You should instead start at index 0.
In the very last loop k runs from 0 to high, but that are too many iterations. It should start from low, and then the index access to Temp should again be adapted by using k-low as index.
Here is the corrected code:
void MergeSort(int arr[],int low,int high)
{
int mid;
if(low<high)
{
mid = (low+high)/2; // <--
MergeSort(arr,low,mid); // <--
MergeSort(arr,mid+1,high); // <--
Merge(arr,low,mid,mid+1,high); // <--
}
}
void Merge(int arr[],int low,int mid1,int mid2, int high)
{
int i,c,j;
c = 0; // <--
i = low;
j = mid2;
int Temp[high-low+1];
while(i <= mid1 && j<= high)
{
if(arr[i]<arr[j])
{
Temp[c] = arr[i];
i++;
c++;
}
else
{
Temp[c] = arr[j];
j++;
c++;
}
}
while(i<=mid1)
{
Temp[c] = arr[i];
i++;
c++;
}
while(j<=high)
{
Temp[c] = arr[j];
j++;
c++;
}
for(int k=low;k<=high;k++) // <--
{
arr[k] = Temp[k-low]; // <--
}
}
Important note: I debugged the code for you, but this is something you can do yourself. Inspect the variables as you step through the code with a debugger, and spot where things are unexpected. It takes some time, but it is a skill a coder needs to learn.

Hoare partition correctness

according to introduction to algorithms I wrote a code for quicksort using Hoare's partition in the codeblocks IDE .The code was successfully built but the sorted array is not displayed on the console,only the unsorted array is displayed followed by a blinking underscore.
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
int partition(int arr[],int p,int r)
{
int i,j,x,temp;
x=arr[p];
i=p-1;
j=r+1;
while(true)
{
do{
j=j-1;
}while(arr[j]<=x);
do{
i=i+1;
}while(arr[i]>=x);
if (i<j)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
else
return j;
}
}
void quicksort(int arr[],int p,int r)
{
if (p<r)
{
int q=partition(arr,p,r);
quicksort(arr,p,q-1);
quicksort(arr,q-1,r);
}
}
void print(int A[],int size)
{
int i;
for(i=0;i<size;i++)
printf("%d ",A[i]);
}
int main()
{
int arr[]={1,12,56,2,67,0,98,23};
int size=sizeof(arr)/sizeof(arr[0]);
printf("\nthe array is\n");
print(arr,size);
quicksort(arr,0,size-1);
printf("\nthe sorted array is\n ");
print(arr,size);
return 0;
}
the output was as follows
the array is
1 12 56 2 67 0 98 23
`
Okay, I refactored your algorithm, based on a guide from wikipedia: https://en.wikipedia.org/wiki/Quicksort
As mentioned in my comment above, the [recursive] quicksort calls used the wrong arguments. But, then, as Weather Vane mentioned, it [still] didn't sort.
Edit: My original post was using Lomuto partitioning instead of Hoare.
The partition algorithm differed from the wiki by using a different initial value for the pivot and using <=,>= on the do/while termination conditions instead of <,>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int
partition(int arr[], int p, int r)
{
int i,
j,
x,
temp;
x = arr[(p + r) / 2];
i = p - 1;
j = r + 1;
while (1) {
do {
i += 1;
} while (arr[i] < x);
do {
j -= 1;
} while (arr[j] > x);
if (i >= j)
return j;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
void
quicksort(int arr[], int p, int r)
{
if (p < r) {
int q = partition(arr, p, r);
quicksort(arr, p, q);
quicksort(arr, q + 1, r);
}
}
void
print(int A[], int size)
{
int i;
for (i = 0; i < size; i++)
printf("%d ", A[i]);
}
int
main()
{
int arr[] = { 1, 12, 56, 2, 67, 0, 98, 23 };
int size = sizeof(arr) / sizeof(arr[0]);
printf("\nthe array is\n");
print(arr, size);
quicksort(arr, 0, size - 1);
printf("\nthe sorted array is\n ");
print(arr, size);
printf("\n");
return 0;
}

Finding next smallest palindrome, infinite loop

I am writing a code to find the next smallest palindrome(integer) . I am (must) using array to deal with too large numbers like below:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
void check_pal(int a[],int max)
{
int i,j,ctr,k;
while(1)
{
for(i=0;i<max;i++)
printf("%d",a[i]);
ctr=0;
k=max-1;
while(a[k]==9)
{
a[k--]=0;//add corner case when k==0
}
a[k]++;
for(i=0,j=max;i<max/2;i++,j--)
{
printf("%d",i);
if(a[i]!=a[j])
{
ctr=1;
break;
}
}
if(ctr==0)
for(i=0;i<max;i++)
{
printf("%d",a[i]);
if(i==max-1)
return;
}
}
}
void int_convert(char * m,int a[] )
{
int i,max;
for(i=0;i<strlen(m);i++)
{
// printf("%c",m[i]);
a[i]=m[i]-'0';
}
max=strlen( m);
printf("%d\n",max);
check_pal(a,max);
}
void main()
{ int a[200],max;
char * m=malloc(sizeof(char)*200);
scanf("%s",m);
int_convert(m,a);
getch();
}
The output result is an infinite loop .
For e.g. for input 45 the output must be 55 but it is resulting in 0000000 ..
Please tell me where I am wrong .
It is not difficult to recognize palindromes:
int is_palindrome(int a[], int max) {
for (int i = 0; i < max/2; i++) {
if (a[i] != a[max-i-1]) {
return 0;
}
}
return 1;
}
It is not difficult to increment the value:
void next_value(int a[], int max) {
int i = max - 1;
a[i]++;
while (i > 0 && a[i] > 9) {
a[i] = 0;
a[i-1]++;
i--;
}
}
It's easy to display the value:
void show(int a[], int max) {
for (int i = 0; i < max; i++) {
printf("%d", a[i]);
}
printf("\n");
}
With this support it's trivial to find the smallest following palindrome:
void check_pal(int a[], int max) {
while (!is_palindrome(a, max)) {
next_value(a, max);
}
show(a, max);
}
By the way, I would call the function find_pal rather than check_pal.

Why is my logic incorrect for my selection sort recursion program?

So my recursion selection sort calls two functions max_index and the swap and at the same time it should recursively swap the stuff, but for some reason it seems to break and explode into fire for certain arrays like the one I have set in main. Does anyone know why this is so? Can someone explain and show me why this isn't working?
int max_index(int arr[], int start, int end)
{
if ( start >= end ) {
return 0;
}
else if ( end - start == 1 ) {
return start;
}
else {
int greatest = max_index(arr, start + 1, end);
if( arr[start] > arr[greatest])
{
return start;
}
else
{
return greatest;
}
}
}
void swap(int arr[], int i, int j) {
int temp;
temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
void rec_ssort(int arr[], int len) {
int start = 0;
int last = len - 1;
//int n = len;
int maxindex = max_index(arr, start, last);
//if(arr[maxindex]>0 || arr[maxindex]<n)
{
if(arr[maxindex]>arr[last])
{
swap(arr, maxindex, last);
return rec_ssort(arr, last);
}
if(arr[maxindex] == arr[last])
{
return rec_ssort(arr, last);
}
}
}
int main(void)
{
int i = 0;
int arr[7] = {2,3,4,1,5,6,7};
int start = 0;
int end = 7;
int stuff = 5;
rec_ssort(arr, end);
for(i = 0; i<7; i++)
printf("%d\n", arr[i]);
}
All recursive methods need a base case (to exit the recursion). Additionally it helps if you can see progress on the recursion happening at every step. Note that you weren't recursing when the maxindex pointed to a value less than last.
This is one way to correct your issues in rec_ssort:
void rec_ssort(int arr[], int len) {
// base case: if we're looking at an empty array we're done.
if (len <= 0) return;
int last = len - 1;
int maxindex = max_index(arr, 0, last);
if (arr[maxindex] > arr[last]) {
swap(arr, maxindex, last);
}
// recursively call with a shorter len
rec_ssort(arr, last);
}

Why is this quicksort routine not working?

I'm trying to use this to sort randomly generated numbers, so I print the random numbers, apply the quicksort and then print the sorted list, but it just gives me the numbers in the same order again.
void quicksort(double x[], int first, int last)
{
int i=first;
int j=last;
if((j-i)<2)
{return;}
else
{
double pivot;
pivot=x[(i+j)/2];
if(i<j)
{
if(x[i]<pivot)
{ ++i; printf("%f\n", i); }
else if(x[j]>pivot)
{ --j; }
else if(x[i]>=pivot && x[j]<=pivot)
{
swap( x[i], x[j] );
++i;
--j;
}
}
quicksort(x, first, i);
quicksort(x, i+1, last);
}
}
You're not showing swap().
If that's a function, there's no way it can succeed since it only gets the values of x[i] and x[i], not any addresses.
If it's a macro, it might work, but of course it's hard to tell without seeing it.
There are a few issues with your implementation. The one that's causing your current problem is most likely the swap function, which if you tested it, I'm guessing probably wouldn't do any swapping. I suggest you replace it with something like this:
void
swap(double a[], int i, in j)
{
double t = a[i];
a[i] = a[j]; a[j] = t;
}
But then after that, there will be other issues in your implementation, because you are not partitioning the list properly.
Here's a reference implementation (I'm taking the pivot to be the first element in the range, which is non-optimal, but not less optimal than picking the middle element).
void
qsort(double a[], int lo, int hi)
{
int i = lo, j = hi - 1;
int pivot = a[i++];
if(i+1 > j) return;
while(i<j)
{
while(i < hi && a[i] < pivot) i++;
while(j > lo && a[j] > pivot) j--;
if(i<j) swap(a, i, j);
}
swap(a, lo, j);
qsort(a, lo, j);
qsort(a, j+1, hi);
}

Resources