97 lines
2.9 KiB
C
Executable File
97 lines
2.9 KiB
C
Executable File
#include "heapsort.h"
|
|
|
|
/******************* Subroutines local to heapsort.c ************************/
|
|
|
|
static void add_to_sort_heap(int *heap, float *sort_values, int index,
|
|
int heap_tail);
|
|
|
|
static int get_top_of_heap_index(int *heap, float *sort_values, int heap_tail,
|
|
int start_index);
|
|
|
|
/********************* Subroutine definitions *******************************/
|
|
|
|
void heapsort(int *sort_index, float *sort_values, int nelem, int start_index) {
|
|
|
|
/* This routine loads sort_index [1..nelem] with nelem values: the indices *
|
|
* of the sort_values [1..nelem] array that lead to sort_values[index] being *
|
|
* decreasing as one goes through sort_index. Sort_values is not changed. */
|
|
|
|
int i;
|
|
|
|
sort_index -= start_index;
|
|
sort_values -= start_index;
|
|
|
|
/* Build a heap with the *smallest* element at the top. */
|
|
|
|
for (i = 1; i <= nelem; i++)
|
|
add_to_sort_heap(sort_index, sort_values, i, i);
|
|
|
|
/* Now pull items off the heap, smallest first. As the heap (in sort_index) *
|
|
* shrinks, I store the item pulled off (the smallest) in sort_index, *
|
|
* starting from the end. The heap and the stored smallest values never *
|
|
* overlap, so I get a nice sort-in-place. */
|
|
|
|
for (i = nelem; i >= 1; i--)
|
|
sort_index[i] = get_top_of_heap_index(sort_index, sort_values, i,
|
|
start_index);
|
|
|
|
sort_index += start_index;
|
|
sort_values += start_index;
|
|
}
|
|
|
|
static void add_to_sort_heap(int *heap, float *sort_values, int index,
|
|
int heap_tail) {
|
|
|
|
/* Adds element index, with value = sort_values[index] to the heap. *
|
|
* Heap_tail is the number of elements in the heap *after* the insert. */
|
|
|
|
unsigned int ifrom, ito; /* Making these unsigned helps compiler opts. */
|
|
int temp;
|
|
|
|
heap[heap_tail] = index;
|
|
ifrom = heap_tail;
|
|
ito = ifrom / 2;
|
|
|
|
while (ito >= 1 && sort_values[heap[ifrom]] < sort_values[heap[ito]]) {
|
|
temp = heap[ito];
|
|
heap[ito] = heap[ifrom];
|
|
heap[ifrom] = temp;
|
|
ifrom = ito;
|
|
ito = ifrom / 2;
|
|
}
|
|
}
|
|
|
|
static int get_top_of_heap_index(int *heap, float *sort_values, int heap_tail,
|
|
int start_index) {
|
|
|
|
/* Returns the index of the item at the top of the heap (the smallest one). *
|
|
* It then rebuilds the heap. Heap_tail is the number of items on the heap *
|
|
* before the top item is deleted. */
|
|
|
|
int index_of_smallest, temp;
|
|
unsigned int ifrom, ito, heap_end;
|
|
|
|
index_of_smallest = heap[1];
|
|
heap[1] = heap[heap_tail];
|
|
heap_end = heap_tail - 1; /* One item deleted. */
|
|
ifrom = 1;
|
|
ito = 2 * ifrom;
|
|
|
|
while (ito <= heap_end) {
|
|
if (sort_values[heap[ito + 1]] < sort_values[heap[ito]])
|
|
ito++;
|
|
|
|
if (sort_values[heap[ito]] > sort_values[heap[ifrom]])
|
|
break;
|
|
|
|
temp = heap[ito];
|
|
heap[ito] = heap[ifrom];
|
|
heap[ifrom] = temp;
|
|
ifrom = ito;
|
|
ito = 2 * ifrom;
|
|
}
|
|
|
|
/*index must have the start_index subracted to be consistent with the original array*/
|
|
return (index_of_smallest - start_index);
|
|
}
|