Properly Partitioning QuickSort Array - c

I'm a beginner in C and I've been trying to code a Quicksort program that can take a randomly generated array of real numbers and its size as its argument, and then sorts the elements in ascending order. I cannot figure out what to put in the array size field in the first recursive call of the function QuickSort, which is meant to represent the subarray A[0...q-1]. As far as I can tell, the rest of the code is fine because when linked to a driver program that generates the random numbers, the program returns the elements, albeit in the incorrect order. I appreciate any help/suggestions.
int Partition(float *,int);
int QuickSort(float *A,int n)
{
int q;
if(n>1){
q = Partition(A,n);
QuickSort(&A[],q); //Trying to figure out what to put in here.
QuickSort(&A[q+1],(n-1)-q); //This recursion sends the subarray A[q+1...n-1] to QuickSort, I think it works fine.
}
}
int Partition(float *A,int n){
int i,j;
float x;
x = A[n-1];
i=0;
for(j=0;j<=n-2;j++){
if(A[j] <= x){
A[i]=A[j];
i = i+1;
}
}
A[i]=A[n-1];
return i;
}

You're only problem is you seem to confuse:
A[i]=something;
with swapping A[i] and something. Add an auxiliary tmp, or write a swap function:
#include<stdio.h>
int Partition(float *,int);
void QuickSort(float *A,int n) {
int q;
if(n>1){
q = Partition(A,n);
QuickSort(A,q); //Trying to figure out what to put in here.
QuickSort(A+q+1,(n-q-1)); //This recursion sends the subarray A[q+1...n-1] to QuickSort, I think it works fine.
}
}
int Partition(float *A,int n){
int i,j;
float x;
float tmp;
x = A[n-1];
i=0;
for(j=0;j<=n-2;j++){
if(A[j] <= x){
tmp = A[i];
A[i]=A[j];
A[j]=tmp;
i = i+1;
}
}
tmp = A[i];
A[i]=A[n-1];
A[n-1]=tmp;
return i;
}
int main() {
float A[] = {3, 4, -5, 10, 21, -9, -1, 7, 8, 10};
QuickSort(A,10);
for(int i = 0; i < 10; i ++)
printf("%f ",A[i]);
return 0;
}

Related

Swap is not done between 2 integers in array in C language

I'm implementing Quick Sort Algorithm in C language, in which at only one particular interchange of 2 values arr[i] and pivot is not being done properly, else all the swapping is done accurately, I have debugged too and tried to understand what is the problem/mistake, maybe it is a logical error.
Here's the code:
#include <stdio.h>
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void quickSort(int arr[], int low, int high)
{
int pvt = arr[high];
int i = low;
int j = high;
while (i < j)
{
while (pvt > arr[i])
i++;
while (pvt <= arr[j])
j--;
if (i < j)
swap(&arr[i], &arr[j]);
}
swap(&arr[i], &pvt);
printArr(arr, high + 1);
}
void main()
{
int arr[] = {10, 16, 8, 12, 15, 6, 3, 9, 5};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);
}
Just after 2-3 minutes, a friend of mine helped me out, that the pivot is not present in the array so with what I'm swapping it with arr[i]? Instead I can swap 2 values for the same result, arr[i] and arr[high]. Got my mistake :P

Choosing a value from a sorted array in C

I'm new to C and I've got a question about arrays.
I need to display an array, containing numbers, easy enough. Then, the troubling part, the user is supposed to enter a value, which represents the ranking of the values in the array, think of it like a list of prices, the lower the entered number, the smaller the printed out number is, and I've got no clue how to do it.
I've tried a bubble sort, which sorts all the numbers in the array, but then what?
For example, the array is 10, 1000, 50 if the user enters 1, they would get 10, the smallest, if they enter 3, they'd get 1000.
Here is the code I stole straight from some website, all this does is arrange the array in a bubble sort
#include <stdio.h>
void swap(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
// A function to implement bubble sort
void bubbleSort(int arr[], int n)
{
int i, j;
for (i = 0; i < n-1; i++)
// Last i elements are already in place
for (j = 0; j < n-i-1; j++)
if (arr[j] > arr[j+1])
swap(&arr[j], &arr[j+1]);
}
/* Function to print an array */
void printArray(int arr[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
// Driver program to test above functions
int main()
{
int arr[] = {25000, 10000, 25000, 90000, 90000, 25000, 25000, 10000, 10000, 25000};
int n = sizeof(arr)/sizeof(arr[0]);
bubbleSort(arr, n);
printf("Sorted array: \n");
printArray(arr, n);
return 0;
}
Any help is appreciated.

C recursive permutations

i have been trying to complete figure out this part of my assignment to no avail for the past day, and require some help or guidance to help understand the problem.
so far i have this:
swap(int A, int B){
int temp;
temp = A;
A = B;
B = temp;
}
int max_array(int array[], int arraySize)
{
int i, max=-32000;
for (i=0; i<arraySize; i++)
{
if (array[i]>max)
{
max=array[i];
}
}
printf("%d \n Max array: ", max)
return(max);
}
int nextPermutation(int array[], int arraySize){
int i;
n = max_array(array, arraySize);
if (int i; n == array[i] && i > 1; i++){
swap(array[i], array[i-1]);
}
else if(int i; n == array[i]; i++){
}
}
void main(){
int intArray[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//int intArray[10] = {1, 10, 3, 9, 8, 6, 7, 2, 4, 5};
nextPermutation(intArray, 10);
int i = 0;
for(i = 0; i < 10; i++){
printf("%d ",intArray[i]);
}
}
But the question that i'm struggling to understand is
"If a1,...,an is an arbitrary permutation (where a1,...,an are the numbers 1, 2, …, n in a probably different order) then the “next” permutation is produced by the
following procedure:
(i) If the maximal element of the array (which is n) is not the first element of the
array, say n=ai , where i>1 , then to produce the "next" permutation you
need to swap ai and ai−1 .
(ii) If the maximal element of the array is in the first position, i.e. n=a1 , then to
produce the “next” permutation to the permutation (a1,...,an)
, first find the “next” permutation to the (n-1)-element permutation (a2,...,an
), and then append a1 to the end of thus obtained array of (n-1) elements."
so it needs to permutate every single possible combination with the array of 1,2,3,4,5,6,7,8,9,10 and then finish when it reaches this point "(n, …, 2, 1). And this is
the only permutation that does not have the "next" permutation to it."
And the function int 'nextPermutation(int array[], int arraySize){' needs to stay the same.
Any help or tips will be excellent!
There are some errors in your program,
swap() function will not affect the program as it doesn't use pass by reference.
max_array() should find the index of the maximum value, not the maximum value itself.
There is no recursion in your program as far as I can see.
main() should return int.
The program fragement given below might give you an idea,
int ct=-1,n=10,temp[10]={0,0,0,0,0,0,0,0,0,0};
int intArray[10]={1,2,3,4,5,6,7,8,9,10};
permute(int k)
{
int i;
temp[k]=++ct;
if(ct==n-1)
{
for(i=0;i<n;i++)
{
printf("%d",intArray[temp[i]]);
}
printf("\n");
}
for(i=0;i<n;i++)
{
if(temp[i]==0)
{
permute(i);
}
}
ct--;
temp[k]=0;
}
int main()
{
permute(0);
}
for swap sample
#include <stdio.h>
void swap(int* A, int* B){
int wk;
wk = *A;
*A = *B;
*B = wk;
}
int main(void){
int array[] = { 1,2,3 };
swap(&array[0], &array[2]);
printf("array[0]=%d, array[2]=%d\n", array[0], array[2]);
return 0;
}

unable to pass array properly in quicksort

Here is my program it is compiling and running without syntax errors.How ever it does not sort the array.The problem lies in where I am passing the array in function
#include<stdio.h>
#include<string.h>
int partition (int *,int,int);
void quicksort (int *,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
length=sizeof(a)/sizeof(a[0]);
quicksort(a,0,length-1);
printf("the sorted array is\n");
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r)
{
int x,j,i,temp,bak;
x=num[r];
i=p-1;
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
{
printf(" %d",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r)
{
int q;
if (p<r)
{
call++;
q=partition(num,p,r);
quicksort(num,p,q-1);
quicksort(num,q+1,r);
}
}
The above way of passing array in functions is that right that is what I want to know because that is giving problem in function partition.
Inside the function partition when swapping happens then I tried printing the array there itself (it is not sorted array but just to see upto what point things reached) then I saw that only 2 or 3 elements of array which I had passed are being printed and rest of the array is lost some where.So my doubt is array is not being passed properly.
To be able to see as what is the problem with array passing in a function I wrote a smaller program ka1.c
#include<stdio.h>
void pass(int *);
int main ()
{
int a[]={3,5,61,32,12};
pass(a);
}
void pass (int *num)
{
int i,j;
j=sizeof(num)/sizeof(num[0]);
for (i=0;i<j;i++)
printf(" %d",num[i]);
}
Now when I run the above code I get output just
3 5
I was expecting the complete array to be printed in output of ka1.c.
Where as if you notice rest of the array is not getting printed.Where did that go?
I have used the same logic in quicksort also hence I feel the error is same in both cases.
UPDATE1
After the comment below I checked the length of array recieved in quicsort.c paritition function via
sizeof(num)/sizeof(num[0]);
and found of original array
int a[]={81, 12, 90, 3, 49, 108, 47};
which is having length 7 here when I passed it in the function partition
the length is only 2.
The same is case with program ka1.c So why only length is 2 in both cases?
UPDATE2
As the suggestions given below now I have passed on the length also
#include<stdio.h>
#include<string.h>
int partition (int *,int,int,int);
void quicksort (int *,int,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,0,length-1,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r,int june)
{
int x,j,i,temp,bak,length;
x=num[r];
i=p-1;
bak=0;
printf("inside the partition\n");
printf("length of june recieved =%d \n",june);
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r,int june)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
printf("before sending to function length of june=%d \n",june);
q=partition(num,p,r,june);
bbc=q-1-p+1;
quicksort(num,p,q-1,bbc);
ccd=r-q-1+1;
quicksort(num,q+1,r,ccd);
}
}
But the program is still failing to print the sorted array.
You can compile and run the above code.
SOLVED
Finally with help of replies below I have been able to solve the above problem.
The mistake lied in function partition in statement
for (j = 0; j <= r - 1; j++)
instead it should have been
for (j = p; j <= r - 1; j++)
note j=p and j=0
here
j=0
is wrong since when recursively second partition is tried to be sorted it started disturbing the first partition and hence the result was also wrong.
In this program I faced a problem in using gdb to debug a recursive function.
Please check this thread also
Debugging recurssion was quite tricky.
SO the correct code is
#include<stdio.h>
#include<string.h>
int partition (int *, int, int, int);
void quicksort (int *, int, int, int);
static int call = 0;
int
main ()
{
int i, j, choice;
int length;
int a[] = { 81, 12, 90, 3, 49, 108, 47 };
i = 0;
printf ("the sorted array is\n");
length = sizeof (a) / sizeof (a[0]);
printf ("length of array %d\n", length);
printf ("quick sort called in main\n");
quicksort (a, 0, length - 1, length);
for (i = 0; i < length; i++)
printf (" %d ", a[i]);
}
int
partition (int *num, int p, int r, int june)
{
int x, j, i, temp, bak, length;
x = num[r];
i = p - 1;
bak = 0;
for (j = p; j <= r - 1; j++)
{
if (num[j] <= x)
{
i = i + 1;
temp = num[i];
num[i] = num[j];
num[j] = temp;
}
}
temp=num[i+1];
num[i + 1] = num[r];
num[r]=temp;
return i + 1;
}
void
quicksort (int *num, int p, int r, int june)
{
int q, bbc, ccd;
if (p < r)
{
call++;
q = partition (num, p, r, june);
bbc = q - 1 - p + 1;
quicksort (num, p, q - 1, bbc);
ccd=r-q+1;
quicksort (num, q + 1, r, ccd);
}
}
The problem is in the way you are calculating the length of teh array.......try simply giving the number of elements in the array as the parameter for the quicksort method....i guess u will have the right answer...
and also i agree to the point made....try and passing the length of the array with the array.....try both and tell me which works...:)
NEW CODE:
#include<stdio.h>
#include<string.h>
//int partition (int *,int,int);
void q_sort(int*,int,int);
void quicksort (int *,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
/*int partition(int *num,int p,int r)
{
int x,j,i,temp,bak,length;
x=num[r];
i=-1;
bak=0;
printf("inside the partition\n");
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
*/
/*void quicksort (int *num,int p,int r)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
q=partition(num,p,r);
bbc=q-1-p+1;
quicksort(num,p,q-1);
ccd=r-q-1+1;
quicksort(num,q+1,r);
}
}*/
void quicksort(int numbers[], int array_size)
{
q_sort(numbers, 0, array_size - 1);
}
void q_sort(int numbers[], int left, int right)
{
int pivot, l_hold, r_hold;
l_hold = left;
r_hold = right;
pivot = numbers[left];
while (left < right)
{
while ((numbers[right] >= pivot) && (left < right))
right--;
if (left != right)
{
numbers[left] = numbers[right];
left++;
}
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right)
{
numbers[right] = numbers[left];
right--;
}
}
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
q_sort(numbers, left, pivot-1);
if (right > pivot)
q_sort(numbers, pivot+1, right);
}
You need to put a ; at the end of the function declaration before main:
void pass(int *) ;
^
You have to pass the size of the array along with the array itself. The function receiving the array cannot determine its size. The receiving function only sees num as a pointer, so when you use sizeof(num) it returns the size of the pointer num, not the size of the memory allocated for the array in the main function. So, you have to do something like this:
#include<stdio.h>
void pass(int *, int);
int main ()
{
int a[]={3,5,61,32,12};
int length;
length = sizeof(a)/sizeof(a[0]);
pass(a, length);
}
void pass (int *num, int size)
{
int i;
for (i=0;i<size;i++)
printf(" %d",num[i]);
}
This post explains a similar issue in more detail:
Passing an array as an argument in C++

mergesort C implementation

i wrote this code in C language on Xcode following the algorithm of mergesort.
The problem is that sometimes i get EXC_BAD_ACCESS and i can't manage where the error is!
The merge algorithm should work (i tried it outside the mergesort function and works!). Thank you for your help and patience!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DIM 6
void mymerge (int v[], int i1,int i2, int last); //mergesort core: merge two ordinated arrays in one bigger ordinated array
void mymergesort (int v[], int lower, int upper);//mergesort
void printv (int v[],int lower, int upper);
int main () {
int i;
srand((unsigned int)time(NULL));
int v[DIM];
for (i=0; i<DIM; i++)
v[i]=rand()%15;
printv(v, 0, DIM-1);
getc(stdin);
mymergesort(v, 0, DIM-1);
printv(v, 0, DIM-1);
}
void printv (int v[],int lower, int upper){
int i;
for (i=lower; i<=upper; i++)
printf("%d\t",v[i]);
}
void mymergesort (int v[], int lower, int upper){
int mid=(upper+lower)/2;
if (upper<lower) {
mymergesort(v, lower, mid);
mymergesort(v, mid+1, upper);
mymerge(v,lower,mid+1,upper);
}
}
void mymerge (int v[], int i1,int i2, int last){
int i=i1,j=i2,k=i1,*vout;
vout=(int*)malloc((last-i1+1)*sizeof(int));
while (i<i2 && j<=last) {
if (v[i]<=v[j]) {
vout[k++]=v[i++];
}else {
vout[k++]=v[j++];
}
}
for (;i<i2;i++) vout[k++]=v[i];
for (;j<=last;j++) vout[k++]=v[j];
for (k=i1; k<=last; k++) v[k]=vout[k];
free(vout);
}
EDIT:
thank you very much! but i think think there is another problem, when I try to sort a bigger array (200 elements), the program doesn't work (i get a malloc error: incorrect checksum for freed object - object was probably modified after being freed). But if I run it from the xCode debugger everything works fine
This: vout=(int*)malloc((last-i1)*sizeof(int)); is wrong.
First, the number of elements you want is last-i1+1, not last-i1 - classic off-by-1. This kind of error is one of the reasons why the convention in C code is to make lower bounds inclusive and upper bounds exclusive - less +1 and -1 you need to do, less opportunity to screw up.
The more serious error is that you index vout starting from i1. If you do it this way, you need to allocate last+1 element for vout, and you never use the first i1 (index 0 .. i1-1).
Fix: First, allocate last-i1+1 elements. Second, initialize k to 0 at the beginning, not i1. Third, change the final copy to be
for (k=i1; k<=last; k++) v[k] = vout[k-i1];
You have two problems. The first is that your calculation of the midpoint is incorrect - you use (upper - lower)/ 2, but this is not guaranteed to lie between lower and upper. What you actually want is lower + (upper - lower) / 2. It's also not necessary to do any work if there's only 1 number in the interval to be sorted - so the mymergesort() function should look like:
void mymergesort (int v[], int lower, int upper)
{
if (upper > lower) {
int mid = lower + (upper - lower)/2;
mymergesort(v, lower, mid);
mymergesort(v, mid+1, upper);
mymerge(v,lower,mid+1,upper);
}
}
The second problem is the one in the mymerge() function already pointed out by Fabian Giesen.
#include<stdio.h>
#include<stdlib.h>
void merge(int *a, int n1, int *b, int n2, int *arr)
{
int i=0, j=0, n=0;
while(i<n1 && j<n2)
{
if (a[i] < b[j])
{
arr[n++] = a[i];
i++;
}
else
{
arr[n++] = b[j];
j++;
}
}
while( i < n1)
arr[n++] = a[i++];
while( j < n2)
arr[n++] = b[j++];
}
void merge_sort(int *a, int n)
{
int left[n/2], right[n-n/2],i=0;
if (n<=1)
return ;
while(i<n/2)
left[i] = a[i++];
while(i<n)
right[i - n/2] = a[i++];
merge_sort( left, n/2 );
merge_sort( right, n-n/2);
merge(left, n/2, right, n-n/2, a);
}
void main()
{
int a[] = { 6, 5, 3, 1,9, 8, 7, 2, 4},i;
merge_sort(a,sizeof(a)/sizeof(a[0]));
for(i=0;i<9;i++)
printf("--%d",a[i]);
printf("\n");
}
-- s.k
#include<stdio.h>
#include<conio.h>
#define max 20
/*** function for merging the adjecent subarrays in sorted order ***/
void merge(int A[max],int n,int low,int high, int mid)
{
int i=low,j=mid+1,k,temp;
while((i<=j)&&(j<=high))
{
if(A[i]>A[j]) /** if element of the second half is greater then exchg and shift **/
{
temp=A[j];
for(k=j;k>i;k--) /** shifting the elements **/
{
A[k]=A[k-1];
}
A[i]=temp;
j++;
}
i++;
}
}
/******* iterative function for merge sort ********/
void merge_sort(int A[max],int n,int low,int high)
{
int mid;
if(low<high) /** terminating condition **/
{
mid=(high+low)/2; /** calculating the mid point ***/
merge_sort(A,n,low,mid); /*** recursive call for left half of the array ***/
merge_sort(A,n,mid+1,high); /*** recursive call for right half of the array ***/
merge(A,n,low,high,mid); /** merging the both parts of the array **/
}
}
/******* begening of the main function **********/
int main()
{
int A[max],n,i;
/** reading the inputs fro users **/
printf("\n enter the size of the array\n");
scanf("%d",&n);
printf("\n enter the array \n");
for(i=0;i<n;i++)
{
scanf("%d",&A[i]);
}
/*** calling merge sort ***/
merge_sort(A,n,0,n-1);
/** printing the sorted array **/
for(i=0;i<10;i++)
{
printf("\n\t%d",A[i]);
}
getch();
return 0;
}

Resources