/*
* Copyright 2011 Steven Gribble
*
* This file is part of the UW CSE 333 course project sequence
* (333proj).
*
* 333proj is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 333proj is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 333proj. If not, see .
*/
#include
#include "sort.h"
// swap array elements i and j
static void Swap(void *arr, uint32_t element_size, uint32_t i, uint32_t j) {
unsigned char tmp[element_size];
// Handle the degenerate case.
if (i == j)
return;
memcpy(tmp,
arr+(element_size*i),
element_size);
memcpy(arr+(element_size*i),
arr+(element_size*j),
element_size);
memcpy(arr+(element_size*j),
tmp,
element_size);
}
// See wikipedia's entry for quicksort (in-place version)
// for algorithm details.
uint32_t QuickSortPartition(void *arr,
uint32_t element_size,
uint32_t left,
uint32_t right,
uint32_t pivot_index,
ComparatorFnPtr f) {
unsigned char pivot_value[element_size];
uint32_t store_index, i;
memcpy(pivot_value, arr+(pivot_index*element_size), element_size);
// Move pivot to end
Swap(arr, element_size, pivot_index, right);
store_index = left;
for (i = left; i < right; i++) {
if (f(arr+(i*element_size), pivot_value) <= 0) {
Swap(arr, element_size, i, store_index);
store_index++;
}
}
// Move pivot to its final place
Swap(arr, element_size, store_index, right);
return store_index;
}
void QuickSortRecurse(void *arr, uint32_t element_size, uint32_t left,
uint32_t right, ComparatorFnPtr f) {
if (right > left) {
uint32_t pivot_index = (left + right) / 2;
uint32_t pivot_new_index = QuickSortPartition(arr,
element_size,
left,
right,
pivot_index,
f);
if (pivot_new_index > 0)
QuickSortRecurse(arr, element_size, left, pivot_new_index-1, f);
QuickSortRecurse(arr, element_size, pivot_new_index+1, right, f);
}
}
void QuickSort(void *arr, uint32_t num_elements, uint32_t element_size,
ComparatorFnPtr f) {
// Handle the easy degenerate case.
if (num_elements <= 1)
return;
// Dive into the recursive quicksort implementation.
QuickSortRecurse(arr, element_size, 0, num_elements-1, f);
}
void BubbleSort(void *arr, uint32_t num_elements, uint32_t element_size,
ComparatorFnPtr f) {
uint32_t i;
int done = 0;
// Handle the easy degenerate case.
if (num_elements <= 1)
return;
// Non-degenerate case.
while (!done) {
done = 1;
for (i = 0; i < num_elements-1; i++) {
if (f(arr+(element_size*i),
arr+(element_size*(i+1))) > 0) {
Swap(arr, element_size, i, i+1);
done = 0;
}
}
}
}