/* * 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 <http://www.gnu.org/licenses/>. */ #include <string.h> #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; } } } }