1. Makefile
.PHONY: clean
CC = gcc
CFLAGS = -g -Wall -DDEBUG -std = c99
SOURCE = $( wildcard ./*.c)
BIN = $( patsubst %.c, %, $( notdir $( SOURCE) ) )
$( BIN) : $( SOURCE)
$( CC) $( CFLAGS) $( EXTRA_FLAGS) $( SOURCE) -o $@
clean:
rm -rf $( BIN)
2. heap.h
# ifndef __HEAP_H__
# define __HEAP_H__
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <limits.h>
# include <stdbool.h>
# ifdef __cplusplus
extern "C" {
# endif
# define MAX_HEAP_SIZE ( 20 )
typedef int heap_data_t;
typedef struct {
heap_data_t data[ MAX_HEAP_SIZE] ;
int size;
} heap_t;
int get_heap_size ( const heap_t * heap) ;
int is_heap_empty ( const heap_t * heap) ;
int is_heap_full ( const heap_t * heap) ;
bool init_heap ( heap_t * heap, heap_data_t data[ ] , int size) ;
void print_heap_info ( const heap_t * heap) ;
void print_array_info ( const heap_data_t data[ ] , int size) ;
# ifndef USE_RECURSION
void adjust_down_heap ( heap_data_t data[ ] , int size, int root) ;
void adjust_up_heap ( heap_t * heap, int child) ;
# else
void adjust_down_heap_recursion ( heap_data_t data[ ] , int size, int root) ;
void adjust_up_heap_recursion ( heap_t * heap, int child) ;
# endif
void build_heap ( heap_t * heap) ;
void heap_push ( heap_t * heap, heap_data_t data) ;
void heap_pop ( heap_t * heap) ;
heap_data_t get_heap_top ( const heap_t * heap) ;
heap_data_t * find_heap_top_minimum_k_data ( heap_data_t data[ ] , int size, int k) ;
heap_data_t * find_heap_top_maximum_k_data ( heap_data_t data[ ] , int size, int k) ;
void heap_sort ( heap_data_t data[ ] , int size) ;
void destroy_heap ( heap_t * heap) ;
# ifdef __cplusplus
}
# endif
# endif
3. heap.c
# include "heap.h"
# ifdef USE_RECURSION
static bool s_is_big_root_heap = false ;
# else
static bool s_is_big_root_heap = true ;
# endif
int get_heap_size ( const heap_t * heap)
{
return NULL == heap ? 0 : heap-> size;
}
int is_heap_empty ( const heap_t * heap)
{
return 0 == get_heap_size ( heap) ;
}
int is_heap_full ( const heap_t * heap)
{
return get_heap_size ( heap) > MAX_HEAP_SIZE;
}
bool init_heap ( heap_t * heap, heap_data_t data[ ] , int size)
{
if ( NULL == heap || size > MAX_HEAP_SIZE) {
printf ( "in %s, size: %d\n" , __func__ , size) ;
return false ;
}
memset ( heap-> data, 0x00 , MAX_HEAP_SIZE * sizeof ( heap_data_t) ) ;
heap-> size = size;
memcpy ( heap-> data, data, size * sizeof ( heap_data_t) ) ;
return true ;
}
static void swap_data ( heap_data_t * a, heap_data_t * b)
{
heap_data_t tmp = * a;
* a = * b;
* b = tmp;
}
static void print_info ( const heap_data_t data[ ] , int size)
{
int i = 0 ;
for ( ; i < size; ++ i) {
printf ( "[%-2d] " , data[ i] ) ;
}
printf ( "\n" ) ;
}
void print_heap_info ( const heap_t * heap)
{
printf ( "%s\n\t" , __func__ ) ;
if ( NULL == heap) {
return ;
}
int size = get_heap_size ( heap) ;
print_info ( heap-> data, size) ;
}
void print_array_info ( const heap_data_t data[ ] , int size)
{
printf ( "%s\n\t" , __func__ ) ;
print_info ( data, size) ;
}
static int get_child_index ( const heap_data_t data[ ] , int size, int root)
{
int child = root;
int left = root * 2 + 1 ;
int right = root * 2 + 2 ;
if ( s_is_big_root_heap) {
if ( ( left < size) && ( data[ left] > data[ child] ) ) {
child = left;
}
if ( ( right < size) && ( data[ right] > data[ child] ) ) {
child = right;
}
} else {
if ( ( left < size) && ( data[ left] < data[ child] ) ) {
child = left;
}
if ( ( right < size) && ( data[ right] < data[ child] ) ) {
child = right;
}
}
return child;
}
# ifdef USE_RECURSION
void adjust_down_heap_recursion ( heap_data_t data[ ] , int size, int root)
{
printf ( "in %s\n" , __func__ ) ;
int child = get_child_index ( data, size, root) ;
if ( child != root) {
swap_data ( data + root, data + child) ;
adjust_down_heap_recursion ( data, size, child) ;
}
}
# else
void adjust_down_heap ( heap_data_t data[ ] , int size, int root)
{
printf ( "in %s\n" , __func__ ) ;
int parent = root;
while ( parent < size) {
int child = get_child_index ( data, size, parent) ;
if ( child != parent) {
swap_data ( data + child, data + parent) ;
parent = child;
} else {
break ;
}
}
}
# endif
static void heapify ( heap_data_t data[ ] , int size)
{
int i = ( size - 1 - 1 ) / 2 ;
printf ( "Build %s root heap\n" , s_is_big_root_heap ? "big" : "little" ) ;
for ( ; i >= 0 ; -- i) {
if ( i >= size) {
printf ( "in %s, invaild parameter, size: %d, i: %d\n" , __func__ , size, i) ;
continue ;
}
# ifdef USE_RECURSION
adjust_down_heap_recursion ( data, size, i) ;
# else
adjust_down_heap ( data, size, i) ;
# endif
}
}
void build_heap ( heap_t * heap)
{
if ( NULL == heap) {
return ;
}
heapify ( heap-> data, get_heap_size ( heap) ) ;
}
# ifdef USE_RECURSION
void adjust_up_heap_recursion ( heap_t * heap, int child)
{
int parent = ( child - 1 ) / 2 ;
if ( s_is_big_root_heap) {
if ( heap-> data[ child] < heap-> data[ parent] ) {
return ;
}
} else {
if ( heap-> data[ child] > heap-> data[ parent] ) {
return ;
}
}
swap_data ( heap-> data + child, heap-> data + parent) ;
if ( 0 == parent) {
return ;
} else {
adjust_up_heap_recursion ( heap, parent) ;
}
}
# else
void adjust_up_heap ( heap_t * heap, int child)
{
int parent = 0 ;
while ( child > 0 ) {
parent = ( child - 1 ) / 2 ;
if ( s_is_big_root_heap) {
if ( heap-> data[ child] < heap-> data[ parent] ) {
break ;
}
} else {
if ( heap-> data[ child] > heap-> data[ parent] ) {
break ;
}
}
swap_data ( heap-> data + child, heap-> data + parent) ;
child = parent;
}
}
# endif
void heap_push ( heap_t * heap, heap_data_t data)
{
if ( NULL == heap || is_heap_full ( heap) ) {
printf ( "heap is NULL or heap full\n" ) ;
return ;
}
heap-> data[ heap-> size++ ] = data;
# ifdef USE_RECURSION
adjust_up_heap_recursion ( heap, heap-> size - 1 ) ;
# else
adjust_up_heap ( heap, heap-> size - 1 ) ;
# endif
}
void heap_pop ( heap_t * heap)
{
if ( NULL == heap || is_heap_empty ( heap) ) {
printf ( "heap is NULL or heap empty\n" ) ;
return ;
}
int size = get_heap_size ( heap) ;
heap-> data[ 0 ] = heap-> data[ size - 1 ] ;
# ifdef USE_RECURSION
adjust_down_heap_recursion ( heap-> data, size, 0 ) ;
# else
adjust_down_heap ( heap-> data, size, 0 ) ;
# endif
}
void heap_sort ( heap_data_t data[ ] , int size)
{
heapify ( data, size) ;
int i = size - 1 ;
for ( ; i > 0 ; -- i) {
swap_data ( data + i, data) ;
# ifdef USE_RECURSION
adjust_down_heap_recursion ( data, i, 0 ) ;
# else
adjust_down_heap ( data, i, 0 ) ;
# endif
}
}
heap_data_t get_heap_top ( const heap_t * heap)
{
return is_heap_empty ( heap) ? INT_MIN : heap-> data[ 0 ] ;
}
static heap_data_t * find_heap_top_k_data ( heap_data_t data[ ] , int size, int k)
{
int i = 0 ;
heap_data_t * top_k_data = NULL ;
do {
top_k_data = ( heap_data_t * ) calloc ( 1 , sizeof ( heap_data_t) * k) ;
if ( NULL == top_k_data) {
perror ( "calloc top_k_data fail" ) ;
break ;
}
memcpy ( top_k_data, data, sizeof ( heap_data_t) * k) ;
heapify ( top_k_data, k) ;
for ( i = k; i < size; ++ i) {
if ( s_is_big_root_heap) {
if ( data[ i] < top_k_data[ 0 ] ) {
top_k_data[ 0 ] = data[ i] ;
}
# ifdef USE_RECURSION
adjust_down_heap_recursion ( top_k_data, k, 0 ) ;
# else
adjust_down_heap ( top_k_data, k, 0 ) ;
# endif
} else {
if ( data[ i] > top_k_data[ 0 ] ) {
top_k_data[ 0 ] = data[ i] ;
}
# ifdef USE_RECURSION
adjust_down_heap_recursion ( top_k_data, k, 0 ) ;
# else
adjust_down_heap ( top_k_data, k, 0 ) ;
# endif
}
}
} while ( 0 ) ;
return top_k_data;
}
heap_data_t * find_heap_top_minimum_k_data ( heap_data_t data[ ] , int size, int k)
{
s_is_big_root_heap = true ;
heap_data_t * top_k_minimum_data = find_heap_top_k_data ( data, size, k) ;
return top_k_minimum_data;
}
heap_data_t * find_heap_top_maximum_k_data ( heap_data_t data[ ] , int size, int k)
{
s_is_big_root_heap = false ;
heap_data_t * top_k_maximum_data = find_heap_top_k_data ( data, size, k) ;
return top_k_maximum_data;
}
void destroy_heap ( heap_t * heap)
{
heap-> size = 0 ;
}
4. test_heap.c
# include "heap.h"
void test ( )
{
heap_t heap;
int i = 0 , data_size = 0 , top_k = 5 ;
int * found_data = NULL ;
heap_data_t data[ ] = {
11 , 12 , 2 , 9 , 8 , 10 , 1
} ;
data_size = sizeof ( data) / sizeof ( heap_data_t) ;
print_array_info ( data, data_size) ;
printf ( "init_heap\n" ) ;
if ( ! init_heap ( & heap, data, data_size) ) {
printf ( "init_heap failed\n" ) ;
return ;
}
build_heap ( & heap) ;
print_heap_info ( & heap) ;
printf ( "Before inserting the data, the top element of the heap is %d\n" , get_heap_top ( & heap) ) ;
heap_push ( & heap, 0 ) ;
print_heap_info ( & heap) ;
printf ( "After inserting the data, the top element of the heap is %d\n" , get_heap_top ( & heap) ) ;
heap_pop ( & heap) ;
printf ( "Pop the heap top data, the top element of the heap is %d\n" , get_heap_top ( & heap) ) ;
found_data = find_heap_top_minimum_k_data ( data, data_size, top_k) ;
printf ( "Find top minimum %d in the data:\n\t" , top_k) ;
for ( i = 0 ; i < top_k; ++ i) {
if ( found_data) {
printf ( "[%-2d] " , found_data[ i] ) ;
}
}
free ( found_data) ;
found_data = NULL ;
printf ( "\n" ) ;
found_data = find_heap_top_maximum_k_data ( data, data_size, top_k) ;
printf ( "Find top maximum %d in the data:\n\t" , top_k) ;
for ( i = 0 ; i < top_k; ++ i) {
if ( found_data) {
printf ( "[%-2d] " , found_data[ i] ) ;
}
}
free ( found_data) ;
found_data = NULL ;
printf ( "\nBefore heap sort, " ) ;
print_array_info ( data, data_size) ;
heap_sort ( data, data_size) ;
printf ( "After heap sort, " ) ;
print_array_info ( data, data_size) ;
printf ( "\ndestroy heap\n" ) ;
destroy_heap ( & heap) ;
printf ( "heap size: %d\n" , get_heap_size ( & heap) ) ;
}
int main ( void )
{
test ( ) ;
return 0 ;
}