/*
* a collection of sort algorithms
*/
/*
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void gnomesort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void insertionsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void selectionsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void shellsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void mergesort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void merge(void *a1, void *a2, size_t n, size_t m, size_t size, int (* compar)(const void *, const void *));
void bubblesort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void quicksort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void heapsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void heapcreate(void *array, size_t count, size_t size, int (* compar)(const void *, const void *));
void siftdown(void *array, size_t count, size_t size, int (* compar)(const void *, const void *), int i);
int cmpint ( void const * a, void const * b );
int randcmp ( void const * a, void const * b );
void plst (int *array, size_t size);
int main ( int argc, char *argv[] ) {
int ls = 30;
int i;
int *lst = (int*) malloc(ls*sizeof(int));
for ( i = 0; i < ls; i++ ) {
*(lst+i) = i;
}
srand(1);
qsort((void*)lst, ls, sizeof(int), randcmp);
plst(lst, ls);
printf("\n\n");
printf("GnomeSort\n");
gnomesort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
qsort((void*)lst, ls, sizeof(int), randcmp);
printf("InsertionSort\n");
insertionsort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
qsort((void*)lst, ls, sizeof(int), randcmp);
printf("SelectionSort\n");
selectionsort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
qsort((void*)lst, ls, sizeof(int), randcmp);
printf("ShellSort\n");
shellsort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
qsort((void*)lst, ls, sizeof(int), randcmp);
printf("MergeSort\n");
mergesort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
qsort((void*)lst, ls, sizeof(int), randcmp);
printf("BubbleSort\n");
bubblesort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
qsort((void*)lst, ls, sizeof(int), randcmp);
printf("QuickSort\n");
quicksort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
qsort((void*)lst, ls, sizeof(int), randcmp);
printf("HeapSort\n");
heapsort((void*)lst, ls, sizeof(int), cmpint);
plst(lst, ls);
printf("\n\n");
free(lst);
exit(0);
}
void plst (int *array, size_t size) {
int i;
for ( i = 0; i < size; i++ ) {
printf("%d, ", *(array+i));
}
}
int randcmp ( void const * a, void const * b ) {
return (int)(3.0*rand()/(RAND_MAX-1))-1;
}
int cmpint ( void const * a, void const * b ) {
int const * const i = a;
int const * const j = b;
if ( *i > *j ) {
return 1;
} else {
if ( *i < *j ) {
return -1;
} else {
return 0;
}
}
}
void gnomesort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int i = 1;
void *t = (void*) malloc(size);
while ( i < count ) {
if ( compar(array+i*size, array+(i-1)*size) < 0 ) {
memcpy(t, array+i*size, size);
memcpy(array+i*size, array+(i-1)*size, size);
memcpy(array+(i-1)*size, t, size);
if ( i > 1 ) {
i--;
} else {
i++;
}
} else {
i++;
}
}
free(t);
}
void insertionsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int i,j;
void *t = (void*) malloc(size);
for ( i = 1; i < count; i++ ) {
j = i-1;
memcpy(t, array+i*size, size);
while ( compar(array+j*size, t) > 0 && j > -1 ) {
memcpy(array+(j+1)*size, array+j*size, size);
j--;
}
memcpy(array+(j+1)*size, t, size);
}
free(t);
}
void selectionsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int i,min,j;
void *t = (void*) malloc(size);
for ( i = 0; i < count-1; i++ ) {
min = i;
for ( j = i+1; j < count; j++ ) {
if ( compar(array+j*size, array+min*size) < 0 ) {
min = j;
}
}
if ( i != min ) {
memcpy(t, array+min*size, size);
memcpy(array+min*size, array+i*size, size);
memcpy(array+i*size, t, size);
}
}
free(t);
}
void shellsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int k,j,i;
void *t = (void*) malloc(size);
for ( k = count; k > 0; k-- ) {
for ( i = k; i < count; i++ ) {
memcpy(t, array+i*size, size);
j = i;
while ( j+1 > k && compar(array+(j-k)*size, t) > 0) {
memcpy(array+j*size, array+(j-k)*size, size);
j = j-k;
}
memcpy(array+j*size, t, size);
}
}
free(t);
}
void mergesort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int m;
if ( count > 1 ) {
m = count/2;
mergesort(array, m, size, compar);
mergesort(array+m*size, count-m, size, compar);
merge(array, array+m*size, m, count-m, size, compar);
}
}
void merge(void *a1, void *a2, size_t n, size_t m, size_t size, int (* compar)(const void *, const void *)) {
int i,c;
int i1 = 0;
int i2 = 0;
void *s = (void*)malloc(size*(n+m));
for ( i = 0; i < n+m; i++ ) {
if ( compar(a1+size*i1, a2+size*i2) < 0 ) {
c = 1;
} else {
c = 0;
}
if ((c && i1 == n) || (!c && i2 == m)) {
c = !c;
}
if ( c ) {
memcpy(s+size*i, a1+size*i1, size);
i1++;
} else {
memcpy(s+size*i, a2+size*i2, size);
i2++;
}
}
memcpy(a1, s, size*(n+m));
free(s);
}
void bubblesort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int r,i;
int c = 1;
void *t = (void*) malloc(size);
for ( r = count-1; c ; r-- ) {
c = 0;
for ( i = 0; i < r; i++ ) {
if ( compar(array+i*size, array+(i+1)*size) > 0) {
memcpy(t, array+i*size, size);
memcpy(array+i*size, array+(i+1)*size, size);
memcpy(array+(i+1)*size, t, size);
c = 1;
}
}
}
free(t);
}
void quicksort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int q = 0;
int p = count-1;
void *t = (void*) NULL;
void *t2 = (void*) NULL;
if ( count > 1 ) {
t = (void*) malloc(size);
t2 = (void*) malloc(size);
memcpy(t, array+(count-1)*size, size);
while ( p > q ) {
for ( ; p > 0 && compar(array+p*size, t) > -1; p-- );
for ( ; q < count-1 && compar(array+q*size, t) < 1; q++ );
if ( p > q ) {
memcpy(t2, array+p*size, size);
memcpy(array+p*size, array+q*size, size);
memcpy(array+q*size, t2, size);
}
}
memcpy(t2, array+q*size, size);
memcpy(array+q*size, array+(count-1)*size, size);
memcpy(array+(count-1)*size, t2, size);
quicksort(array, q, size, compar);
quicksort(array+(q+1)*size, count-q-1, size, compar);
free(t);
free(t2);
}
}
void heapsort(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int i,j,s,l;
void *t = (void*) malloc(size);
heapcreate(array, count, size, compar);
for ( i = count-1; i > 0; i-- ) {
memcpy(t, array, size);
memcpy(array, array+(i)*size, size);
memcpy(array+(i)*size, t, size);
s = 1;
j = 0;
while ( s && j < i ) {
s = 0;
if ( 2*j < count ) {
if ( 2*j+1 < count ) {
if ( compar(array+2*j*size, array+(2*j+1)*size) > 0 ) {
l = 2*j;
} else {
l = 2*j+1;
}
} else {
l = 2*j;
}
} else {
break;
}
if ( l > i-1) {
break;
}
if ( compar(array+l*size, array+j*size) > 0 ) {
memcpy(t, array+l*size, size);
memcpy(array+l*size, array+j*size, size);
memcpy(array+j*size, t, size);
j = l;
s = 1;
}
}
}
free(t);
}
void heapcreate(void *array, size_t count, size_t size, int (* compar)(const void *, const void *)) {
int i;
for ( i = (count-2)/2; i > -1; i-- ) {
siftdown(array, count, size, compar, i);
}
}
void siftdown(void *array, size_t count, size_t size, int (* compar)(const void *, const void *), int i) {
int j;
int s = 1;
void *t = (void*) malloc(size);
while ( s && 2*i+1 < count ) {
s = 0;
if ( compar(array+2*i*size, array+(2*i+1)*size) > 0) {
j = 2*i;
} else {
j = 2*i+1;
}
if ( compar(array+j*size, array+i*size) > 0 ) {
memcpy(t, array+j*size, size);
memcpy(array+j*size, array+i*size, size);
memcpy(array+i*size, t, size);
i = j;
s = 1;
}
}
free(t);
}