Subversion Repositories programming

Rev

Rev 87 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* sorts.c - A holder for some common sorts
 *
 * Written By: Ira Snyder
 * Started On: 06-02-2005
 * 
 * License: MIT License
 * License: http://www.opensource.org/licenses/mit-license.php
 *
 * These are all tested and work as long as you give them correct
 * values. DO NOT try giving them a size larger than the array, for example.
 */

#ifndef SORTS_C
#define SORTS_C

#include <stdlib.h> /* for qsort() */

/* include some common functions for dealing with arrays */
#include "arrays.c"

/* ---------- FUNCTION PROTOTYPES ---------- */

/* quicksort -- O(n*logn) best, average. O(n^2) worst */
int cmp_func (const void* _a, const void* _b);
void quicksort (int array[], unsigned long size);

/* mergesort -- O(n*logn) best, average, worst */
void mergesort (int array[], unsigned long size);
void mergesort_rec (int A[], unsigned long min, unsigned long max);
void merge (int A[], unsigned long asize, int B[], unsigned long bsize);

/* insertsort & selectsort -- O(n^2) sorts */
void insertsort (int array[], unsigned long size);
void selectsort(int array[], unsigned long size);

/* swap -- O(1) */
void swap (int *left, int *right);

/* partition -- O(n) way to move an array around a pivot
 *           -- comes from quicksort() (but is not used here) */
int partition (int array[], unsigned long left, unsigned long right);

/* ---------- BEGIN QUICKSORT ---------- */

/* compare function for stdlib's qsort() */
int cmp_func (const void* _a, const void* _b)
{
    const int* a = (const int*) _a;
    const int* b = (const int*) _b;

    if (*a > *b)
        return 1;
    else if (*a == *b)
        return 0;
    else
        return -1;
}

/* wrapper for stdlib's qsort() */
void quicksort (int array[], unsigned long size)
{
    qsort ((void*)array, size, sizeof(int), cmp_func);
}

/* ---------- END QUICKSORT ---------- */

/* ---------- BEGIN MERGESORT ---------- */

/* Mergesort an array
 * Sets up the correct parameters and hands off the work to
 * mergesort_rec()
 * 
 * Complexity: O(n*lgn) */
void mergesort (int array[], unsigned long size)
{
    mergesort_rec (array, 0, size-1);
}

/* The actual mergesort call */
void mergesort_rec (int A[], unsigned long min, unsigned long max)
{
    unsigned long mid = (min+max)/2;
    unsigned long lowerCount = mid - min + 1;
    unsigned long upperCount = max - mid;

    if (max == min)
        return;

    mergesort_rec (A, min, mid);
    mergesort_rec (A, mid+1, max);
    merge (A+min, lowerCount, A+mid+1, upperCount);
}

/* merge two arrays together
 *
 * Complexity: O(n) */
void merge(int A[], unsigned long asize, int B[], unsigned long bsize)
{
    unsigned long ai, bi, ci, i;
    int *C;
    unsigned long csize = asize+bsize;

    C = create_array (csize);

    ai = 0;
    bi = 0;
    ci = 0;
   
    while ((ai < asize) && (bi < bsize)) 
    {
        if (A[ai] <= B[bi])
        {
            C[ci] = A[ai];
            ci++; ai++;
        }
        else
        {
            C[ci] = B[bi];
            ci++; bi++;
        }
    }

    if (ai >= asize)
        for (i = ci; i < csize; i++, bi++)
            C[i] = B[bi];
        else if (bi >= bsize)
            for (i = ci; i < csize; i++, ai++)
                C[i] = A[ai];

        for (i = 0; i < csize; i++)
            A[i] = C[i];

    C = free_array (C);
}

/* ---------- END MERGESORT ---------- */

/* ---------- BEGIN INSERTION SORT ---------- */

void insertsort (int array[], unsigned long size)
{
    int i, j, v;
    
    for (i=1; i<size; i++)
    {
        v = array[i];
        j = i;

        while (array[j-1] > v)
        {
            array[j] = array[j-1];
            j--;

            if (j <= 0)
                break;
        }
        
        array[j] = v;
    }
}

/* ---------- END INSERTION SORT ---------- */

/* ---------- BEGIN SELCTION SORT ---------- */

void selectsort(int array[], unsigned long size)
{
    int i, j, min;

    for (i=0; i<size-1; i++)
    {
        min = i;
        for (j=i+1; j<size; j++)
            if (array[j] < array[min])
                min = j;
        
        swap (&array[i], &array[min]);
    }
}

/* ---------- END SELECTION SORT ---------- */

/* ---------- BEGIN GENERIC SWAP ---------- */

/* swap two values */
void swap (int *left, int *right)
{
    int temp;
    temp = *left;
    *left = *right;
    *right = temp;
}

/* ---------- END GENERIC SWAP ---------- */

/* ---------- BEGIN PARTITION ---------- */

/* partition from quicksort
 * this partitions an array around the pivot value,
 * which is found in array[left].
 *
 * All values less than the pivot are on the left
 * All values more than the pivot are on the right
 *
 * Complexity: O(n) */
int partition (int array[], unsigned long left, unsigned long right)
{
    unsigned long i, last, pivot;

    pivot = array[left];
    last = left;
        
    for (i=left+1; i<=right; i++)
        if (array[i] < pivot)
        {
           last++;
           swap (&array[last], &array[i]);
        }

    swap (&array[left], &array[last]);
    return last;
}

/* ---------- END PARTITION ---------- */

#endif