It's been 2 days I'm trying to write a quicksort implementation in C but it does not work. I mean, it does compile but the output is not what I expected.
I have been studying a Data Struct book, it's translated to portuguese tho, my native language, anyway... I'll past the instructions here below along with my code.
QuickSort Image Partition Image
//
// Quick sort V2.c
// IFTM Exercises
//
// Created by Lelre Ferreira on 7/9/19.
// Copyright © 2019 Lelre Ferreira. All rights reserved.
//
#define size 5
#include <stdio.h>
void printfArrays(int *array);
void receiveArray(int *array);
int QuickSortPartition(int *array, int begin, int end);
void QuickSortFunction(int *array, int begin, int end);
int main (int argc, const char * argv[]){
int array[size];
receiveArray(array);
printfArrays(array);
return 0;
}
void receiveArray(int* array){
int i = 0;
for (i = 0; i < size; i++) {
printf("Insert value of [%d]: ", i);
scanf("%d", &array[i]);
}
}
void printfArrays(int *array){
int i = 0;
for (i = 0; i < size; i++) {
printf("Value sorted: %d\n", array[i]);
}
}
int QuickSortPartition(int *array, int begin, int end){
int pivot = array[end];
int i = (begin - 1), j = 0;
for (j = begin; j <= end - 1; j++) {
if (array[j] <= pivot) {
i++;
array[i] = array[j];
}
}
array[i + 1] = array[end];
return (i + 1);
}
void QuickSortFunction(int *array, int begin, int end){
if (begin < end) {
int pivot = QuickSortPartition(array, begin, end);
QuickSortPartition(array, begin, pivot - 1);
QuickSortPartition(array, pivot + 1, end);
}
}
Two things wrong:
Whatever translation you performed for that algorithm for (2), it's wrong. The general algorithm for a Lomuto partition with a fixed pivot selection always at the end (a terrible choice, but that's beyond the scope of this question) is as follows:
Updated Partition Function
// added to make the partition algorithm easier to understand.
void swap_int(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int QuickSortPartition(int *array, int begin, int end){
int i=begin, j;
for (j = begin; j <= end; j++)
{
if (array[j] < array[end])
swap_int(array+j, array + i++);
}
swap_int(array+i, array+end);
return i;
}
Here i
denotes the active slot where the pivot value will eventually reside. Initially the pivot is stored at array[end]
. Once the for-loop sweep is done, i
is sitting on the slot where the final swap will put the pivot into place. It is also the return value of the function, used by the caller to denote what not to include in later recursions (because its value is already home).
The final result looks like this:
#include <stdio.h>
void printfArrays(int *array);
void receiveArray(int *array);
int QuickSortPartition(int *array, int begin, int end);
void QuickSortFunction(int *array, int begin, int end);
#define size 5
int main (int argc, const char * argv[]){
int array[size];
receiveArray(array);
QuickSortFunction(array, 0, size-1);
printfArrays(array);
return 0;
}
void receiveArray(int* array){
int i = 0;
for (i = 0; i < size; i++) {
printf("Insert value of [%d]: ", i);
scanf("%d", array+i);
}
}
void printfArrays(int *array){
int i = 0;
for (i = 0; i < size; i++) {
printf("Value sorted: %d\n", array[i]);
}
}
static void swap_int(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int QuickSortPartition(int *array, int begin, int end){
int i=begin, j;
for (j = begin; j <= end; j++)
{
if (array[j] < array[end])
swap_int(array+j, array + i++);
}
swap_int(array+i, array+end);
return i;
}
void QuickSortFunction(int *array, int begin, int end){
if (begin < end) {
int pivot = QuickSortPartition(array, begin, end);
QuickSortFunction(array, begin, pivot - 1);
QuickSortFunction(array, pivot + 1, end);
}
}
Input
4 1 3 5 2
Output
Value sorted: 1
Value sorted: 2
Value sorted: 3
Value sorted: 4
Value sorted: 5
There are a multitude of other unrelated things in this code that would be wise to address (checking IO, a better pivot selection scheme such as median-of-three, etc.), but the basic problems are addressed above.