www.pudn.com > HSORT.rar > HSORT.C
/***********************************************************************/ /* HSORT(): Heap Sort function. */ /* See the function declaration for calling information. */ /* Set STANDALONE != 0 to compile a shell to test the sucker; */ /* to compile just hsort() and its supporting functions, set */ /* STANDALONE = 0. */ /* DEBUG determines how much debugging info is displayed; 0 is none. */ /* TRACE determines what level of tracing information is displayed; */ /* 0 is none. */ /* Function is by Bruce Feist; please contact me on CompuServe with */ /* a message on BORPRO or through EASYPLEX if you have any */ /* questions or problems. */ /* Feel free to make use of this code in your own programs. */ /***********************************************************************/ #define DEBUG 0 #define STANDALONE 0 #define TRACE 0 #include#include #include #include #include static void pascal swap (unsigned int, unsigned int); static void pascal buildheap (void); static void pascal heapify (unsigned int, unsigned int); void hsort (void *, unsigned int, unsigned int, int (*)()); #if STANDALONE static int int_compare (int *, int *); static void showarray (int *, unsigned int, unsigned int); void main() { unsigned int n_entries, entry_num; int *entries; printf ("How many entries do you wish to sort? "); scanf ("%d", &n_entries); entries = (int *) malloc (n_entries * sizeof(int)); for (entry_num = 0; entry_num < n_entries; entry_num++) { printf ("Enter #%d: ", entry_num); scanf ("%d", entries + entry_num); } printf ("\n"); hsort (entries, n_entries, sizeof (int), int_compare); showarray (entries, 0, n_entries - 1); exit (0); } int int_compare (i, j) int *i, *j; { return (*i - *j); } void showarray(base, bot, top) int *base; unsigned int bot, top; { unsigned int i; for (i=bot; i<=top; i++) printf("%4d", base[i]); printf ("\n"); } #endif /* STANDALONE */ static int (*static_compare) (void *, void *), static_width, static_n_elements; static void *temp_element, *static_base; void hsort(base, n_elements, element_width, compare) /***************************************************************************/ /* Heap Sort routine -- similar in calling sequence to standard 'qsort()' */ /* Base is a pointer to an array */ /* n_elements is the number of elements in the array */ /* element_width is the width of each element in bytes */ /* compare is a function of two pointers (each to an element of the array) */ /* returning a negative value if the first is smaller, a positive value */ /* if the second is smaller, or 0 if they should be sorted the same. */ /* Warning! This function will halt your program if it can't allocate */ /* element_width bytes using malloc(). */ /***************************************************************************/ void *base; unsigned int n_elements, element_width; int (*compare)(); { register unsigned int i; #if TRACE >= 1 printf("hsort(base at %lX, %u elements, width %u, compare at %ld)\n", (long) base, n_elements, element_width, (long) compare); #endif /* this lets us reference elements of array as 1 to n */ (char *) base -= element_width; /* The following assignments to static variables reduce the */ /* overhead of subroutine calls later. */ static_width = element_width; static_compare = compare; static_n_elements = n_elements; static_base = base; temp_element = malloc (element_width); if (temp_element == NULL) { fputs ("Unable to allocate room for a temporary element in hsort().\n", stderr); exit (1); } buildheap (); for (i = n_elements; i>1; i--) { swap (1, i); heapify (1, i-1); } free (temp_element); } static void pascal swap (i, j) unsigned int i,j; { register int temp_int; long temp_long; #if TRACE >= 2 printf("swap (i=%d, j=%d) called.\n",i,j); #endif switch (static_width) { case sizeof (int): temp_int = ((int *) static_base) [i]; ((int *) static_base) [i] = ((int *) static_base) [j]; ((int *) static_base) [j] = temp_int; break; case sizeof(long): temp_long = ((long *) static_base) [i]; ((long *) static_base) [i] = ((long *) static_base) [j]; ((long *) static_base) [j] = temp_long; break; case sizeof(char): temp_int = ((char *) static_base) [i]; ((char *) static_base) [i] = ((char *) static_base) [j]; ((char *) static_base) [j] = (char) temp_int; break; default: memcpy (temp_element, (char *) static_base + i*static_width, static_width); memcpy ((char *) static_base + i*static_width, (char *) static_base + j*static_width, static_width); memcpy ((char *) static_base + j*static_width, temp_element, static_width); break; } /* end of switch */ #if TRACE >= 2 printf ("swap exited.\n"); #endif } static void pascal buildheap() { register unsigned int element_number; #if TRACE >= 2 printf("buildheap() called.\n"); #endif for (element_number = static_n_elements >> 1; element_number >= 1; element_number--) { #if DEBUG >= 2 printf ("buildheap calls heapify (%d, %d).\n", element_number, static_n_elements); #endif heapify(element_number, static_n_elements); } #if TRACE >= 2 printf ("buildheap exited.\n"); #endif } #define son1(i) (i << 1) #define son2(i) ((i << 1) + 1) #define pointer(i) ((char *) static_base + i * static_width) #define child_count(i, j) \ (j > son1(i) \ ? 2 \ : j < son1(i) \ ? 0 \ : 1) static void pascal heapify (i,j) unsigned int i, j; { /* The following are static to avoid recursive stack overhead */ static unsigned int son1i, son2i; static void *pson1, *pson2, *pi; static unsigned int k; #if TRACE >= 3 printf("heapify(i=%d, j=%d) called.\n", i, j); #endif son1i = son1 (i); son2i = son2 (i); pson1 = pointer (son1i); pson2 = pointer (son2i); pi = pointer (i); #if DEBUG >= 2 printf ("child_count (%d) = %d.\n", i, child_count(i, j)); #endif switch (child_count (i, j)) { case 0: break; case 2: { k = (*static_compare) (pson1, pson2) > 0 ? son1i : son2i; if ((*static_compare) (pi, pointer (k)) < 0) { #if STANDALONE && DEBUG >= 1 printf ("heapify changes\n"); showarray (static_base, 1, static_n_elements); #endif swap (i, k); heapify (k, j); #if STANDALONE && DEBUG >= 1 printf ("into\n"); showarray (static_base, 1, static_n_elements); #endif } break; } /* end case */ case 1: if ((*static_compare) (pi, pson1) < 0) { #if STANDALONE && DEBUG >= 1 printf ("heapify changes\n"); showarray (static_base, 1, static_n_elements); #endif swap (i, son1i); heapify (son1i, j); #if STANDALONE && DEBUG >= 1 printf ("into\n"); showarray (static_base, 1, static_n_elements); #endif } break; } /* end of case */ #if TRACE >= 3 printf ("heapify exited.\n"); #endif }