堆的定义:
1. 堆是一个完全二叉树(最底层的节点都集中在左边,其它各层的节点都是满的)。
2. 父节点的值总是大于(或者小于)左右子节点的值。
3. 父节点的左右子树都是一个最大堆(或者最小堆)。
堆的存储:
一般情况下都使用数组来表示堆,i节点的父节点的下标为(i-1)/2,它的左右子节点的下标分别为i*2+1和i*2+2。下标从0开始。
插入:
插入一个节点,先插到堆的最末尾,然后比较这个节点的值跟其父节点值的大小,如果大于(对于最大堆来说是大于,对于最小堆是小于)父节点的值,则交换这两个节点的值,继续向上进行比较。
删除:
堆的删除都是从堆顶开始,删除根节点,然后把最后一个节点挪到根节点的位置,比较这个节点跟它的两个子节点的值的大小,如果这个值小于(对于最大堆来说是小于,对于最小堆是大于)两个子节点中比较大的值(最小堆是选择比较小的值),则交换这两个节点的值,继续向下进行比较。
层次遍历:
数的层次遍历,需要用到队列,先把根节点enqueue到队列中,然后循环判断队列是否为空,如果不为空,则dequeue队列头的节点并输入这个节点的值,把这个节点的左节点和右节点enqueue到队列中,继续下一个循环过程,直到队列中所有的节点都dequeue出来了,层次遍历结束。
queue.h
#ifndef __queue_h__
#define __queue_h__
#include "heap.h"
#define DEFAULT_QUEUE_SIZE 32
#define DEFAULT_INCREAM_SIZE 8
typedef struct _queue {
uint _size;
uint _head;
uint _tail;
PHEAPNODE *_nodes;
} QUEUE, *PQUEUE;
PQUEUE queue_create ();
void queue_destroy ( PQUEUE pqueue );
int queue_enqueue ( PQUEUE pqueue, PHEAPNODE pnode );
PHEAPNODE queue_dequeue ( PQUEUE pqueue );
uint queue_size ( PQUEUE pqueue );
int queue_empty ( PQUEUE pqueue );
#endif // __queue_h__
queue.c
#include "queue.h"
#include <stdio.h>
#include <malloc.h>
PQUEUE queue_create()
{
PQUEUE pqueue = (PQUEUE)malloc( sizeof(QUEUE) );
if( NULL != pqueue ) {
pqueue->_nodes = (PHEAPNODE*)malloc( sizeof(PHEAPNODE) * DEFAULT_QUEUE_SIZE );
if( NULL != pqueue->_nodes ) {
pqueue->_size = DEFAULT_QUEUE_SIZE;
pqueue->_head = -1;
pqueue->_tail = -1;
}
else {
free( pqueue );
pqueue = NULL;
}
}
return pqueue;
}
void queue_destroy( PQUEUE pqueue )
{
if( NULL == pqueue )
return;
free( pqueue->_nodes );
free( pqueue );
pqueue = NULL;
}
int queue_enqueue( PQUEUE pqueue, PHEAPNODE pnode )
{
PHEAPNODE *pnodes = NULL;
uint i = 0;
if( NULL == pqueue || NULL == pqueue->_nodes )
return 0;
if( -1 == pqueue->_head )
pqueue->_head = 0;
else if( (pqueue->_tail + 1) == pqueue->_size ) {
pnodes = (PHEAPNODE*)malloc( sizeof(PHEAPNODE) * (pqueue->_size + DEFAULT_INCREAM_SIZE) );
for( i = pqueue->_head; i <= pqueue->_tail; i++ )
pnodes[i] = pqueue->_nodes[i];
free( pqueue->_nodes );
pqueue->_nodes = pnodes;
pqueue->_size += DEFAULT_INCREAM_SIZE;
}
pqueue->_nodes[pqueue->_tail + 1] = pnode;
pqueue->_tail++;
return 1;
}
PHEAPNODE queue_dequeue( PQUEUE pqueue )
{
if( NULL == pqueue || NULL == pqueue->_nodes )
return NULL;
if( pqueue->_head > pqueue->_tail )
return NULL;
return pqueue->_nodes[pqueue->_head++];
}
int queue_empty( PQUEUE pqueue )
{
if( NULL == pqueue || NULL == pqueue->_nodes )
return 1;
if( -1 == pqueue->_head )
return 1;
if( pqueue->_head > pqueue->_tail )
return 1;
return 0;
}
heap.h
#ifndef __heap_h__
#define __heap_h__
#ifndef DLLEXPORT
#define DLLAPI __declspec(dllimport)
#else
#define DLLAPI __declspec(dllexport)
#endif
typedef unsigned int uint;
typedef uint Data;
typedef struct _heap_node {
Data _data;
struct _heap_node *_parent;
struct _heap_node *_left;
struct _heap_node *_right;
} HEAPNODE, *PHEAPNODE;
typedef enum {
HEAP_MINIMUM,
HEAP_MAXIMUM
} eHeapType;
typedef struct _heap {
eHeapType _type;
PHEAPNODE _root;
} HEAP, *PHEAP;
typedef void (*visit_func)( PHEAPNODE pnode );
#ifdef __cplusplus
extern "C" {
#endif
PHEAP DLLAPI heap_create ( eHeapType type );
PHEAP DLLAPI heap_from_array ( eHeapType type, Data *pdata, uint num );
void DLLAPI heap_destroy ( PHEAP pheap );
int DLLAPI heap_insert ( PHEAP pheap, Data data );
void DLLAPI heap_remove ( PHEAP pheap );
void DLLAPI heap_to_array ( PHEAP pheap, Data *pdata, uint num );
void DLLAPI heap_pre_order_visit ( PHEAP pheap, visit_func pvf );
void DLLAPI heap_in_order_visit ( PHEAP pheap, visit_func pvf );
void DLLAPI heap_post_order_visit ( PHEAP pheap, visit_func pvf );
void DLLAPI heap_order_visit ( PHEAP pheap, visit_func pvf );
PHEAPNODE DLLAPI heap_find_data ( PHEAP pheap, Data data );
uint DLLAPI heap_node_count ( PHEAP pheap );
#ifdef __cplusplus
}
#endif
#endif // __heap_h__
heap.c
#define DLLEXPORT
#include "heap.h"
#include "queue.h"
#include <stdio.h>
#include <malloc.h>
//============================================================================//
static void s_heap_delete_node ( PHEAPNODE pnode );
static PHEAPNODE s_heap_find_insert_pos ( PHEAP pheap );
static PHEAPNODE s_heap_find_last_node ( PHEAP pheap );
static void s_heap_pre_order_visit ( PHEAPNODE pnode, visit_func pvf );
static void s_heap_in_order_visit ( PHEAPNODE pnode, visit_func pvf );
static void s_heap_post_order_visit ( PHEAPNODE pnode, visit_func pvf );
static void s_heap_order_visit ( PHEAPNODE pnode, visit_func pvf );
static PHEAPNODE s_heap_find_data ( PHEAPNODE pnode, Data data );
static uint s_heap_node_count ( PHEAPNODE pnode );
//============================================================================//
PHEAP DLLAPI heap_create( eHeapType type )
{
PHEAP pheap = (PHEAP)malloc( sizeof(HEAP) );
if( NULL != pheap ) {
pheap->_type = type;
pheap->_root = NULL;
}
return pheap;
}
void DLLAPI heap_destroy( PHEAP pheap )
{
if( NULL == pheap )
return;
s_heap_delete_node( pheap->_root );
free( pheap );
pheap = NULL;
return;
}
PHEAP DLLAPI heap_from_array( eHeapType type, Data *pdata, uint num )
{
PHEAP pheap = NULL;
uint i = 0;
if( NULL == pdata || 0 == num )
return NULL;
pheap = heap_create( type );
if( NULL == pheap )
return pheap;
for( i = 0; i < num; i++ )
heap_insert( pheap, pdata[i] );
return pheap;
}
void DLLAPI heap_to_array( PHEAP pheap, Data *pdata, uint num )
{
PQUEUE pqueue = NULL;
int index = 0;
PHEAPNODE p = NULL;
if( NULL == pheap || NULL == pheap->_root || NULL == pdata || 0 == num )
return;
pqueue = queue_create();
if( NULL == pqueue )
return;
queue_enqueue( pqueue, pheap->_root );
while( !queue_empty(pqueue) ) {
p = queue_dequeue(pqueue);
if( NULL == p )
break;
pdata[index++] = p->_data;
if( index == num )
break;
queue_enqueue( pqueue, p->_left );
queue_enqueue( pqueue, p->_right );
}
queue_destroy( pqueue );
}
int DLLAPI heap_insert( PHEAP pheap, Data data )
{
PHEAPNODE parent = NULL;
PHEAPNODE child = NULL;
if( NULL == pheap )
return 0;
if( NULL == pheap->_root ) {
pheap->_root = (PHEAPNODE)malloc( sizeof(HEAPNODE) );
if( NULL == pheap->_root )
return 0;
else {
pheap->_root->_data = data;
pheap->_root->_parent = pheap->_root->_left = pheap->_root->_right = NULL;
return 1;
}
}
if( heap_find_data(pheap, data) )
return 0;
parent = s_heap_find_insert_pos(pheap);
if( NULL == parent )
return 0;
else {
child = (PHEAPNODE)malloc( sizeof(HEAPNODE) );
if( NULL == child )
return 0;
child->_data = data;
child->_parent = parent;
child->_left = child->_right = NULL;
if( NULL == parent->_left )
parent->_left = child;
else
parent->_right = child;
if( HEAP_MAXIMUM == pheap->_type ) {
while( child->_data > parent->_data ) {
child->_data = parent->_data;
parent->_data = data;
child = parent;
parent = child->_parent;
if( NULL == parent )
break;
}
}
else {
while( child->_data < parent->_data ) {
child->_data = parent->_data;
parent->_data = data;
child = parent;
parent = child->_parent;
if( NULL == parent )
break;
}
}
return 1;
}
}
void DLLAPI heap_remove( PHEAP pheap )
{
PHEAPNODE plast = NULL;
PHEAPNODE parent = NULL;
PHEAPNODE child = NULL;
PHEAPNODE left = NULL;
PHEAPNODE right = NULL;
Data temp = 0;
if( NULL == pheap || NULL == pheap->_root )
return;
plast = s_heap_find_last_node( pheap );
if( pheap->_root != plast ) {
pheap->_root->_data = plast->_data;
parent = plast->_parent;
if( parent->_left == plast )
parent->_left = NULL;
else
parent->_right = NULL;
parent = pheap->_root;
while( NULL != parent ) {
child = NULL;
left = parent->_left;
right = parent->_right;
if( HEAP_MAXIMUM == pheap->_type ) {
if( NULL != left && parent->_data < left->_data &&
(NULL == right || (NULL != right && right->_data < left->_data)) )
child = left;
else if( NULL != right && parent->_data < right->_data &&
(NULL == left || (NULL != left && left->_data < right->_data)) )
child = right;
else
break;
temp = parent->_data;
parent->_data = child->_data;
child->_data = temp;
parent = child;
}
else {
if( NULL != left && parent->_data > left->_data &&
(NULL == right || (NULL != right && right->_data > left->_data)) )
child = left;
else if( NULL != right && parent->_data > right->_data &&
(NULL == left || (NULL != left && left->_data > right->_data)) )
child = right;
else
break;
temp = parent->_data;
parent->_data = child->_data;
child->_data = temp;
parent = child;
}
}
}
free( plast );
plast = NULL;
}
void DLLAPI heap_pre_order_visit( PHEAP pheap, visit_func pvf )
{
if( NULL == pheap || NULL == pheap->_root || NULL == pvf )
return;
s_heap_pre_order_visit( pheap->_root, pvf );
}
void DLLAPI heap_in_order_visit( PHEAP pheap, visit_func pvf )
{
if( NULL == pheap || NULL == pheap->_root || NULL == pvf )
return;
s_heap_in_order_visit( pheap->_root, pvf );
}
void DLLAPI heap_post_order_visit( PHEAP pheap, visit_func pvf )
{
if( NULL == pheap || NULL == pheap->_root || NULL == pvf )
return;
s_heap_post_order_visit( pheap->_root, pvf );
}
void DLLAPI heap_order_visit( PHEAP pheap, visit_func pvf )
{
if( NULL == pheap || NULL == pheap->_root || NULL == pvf )
return;
s_heap_order_visit( pheap->_root, pvf );
}
PHEAPNODE DLLAPI heap_find_data( PHEAP pheap, Data data )
{
if( NULL == pheap || NULL == pheap->_root )
return NULL;
return s_heap_find_data( pheap->_root, data );
}
uint DLLAPI heap_node_count( PHEAP pheap )
{
if( NULL == pheap || NULL == pheap->_root )
return 0;
return s_heap_node_count( pheap->_root );
}
//============================================================================//
void s_heap_delete_node( PHEAPNODE pnode )
{
if( NULL == pnode )
return;
if( NULL != pnode->_left )
s_heap_delete_node( pnode->_left );
if( NULL != pnode->_right )
s_heap_delete_node( pnode->_right );
free( pnode );
pnode = NULL;
}
void s_heap_pre_order_visit( PHEAPNODE pnode, visit_func pvf )
{
pvf( pnode );
if( NULL != pnode->_left )
s_heap_pre_order_visit( pnode->_left, pvf );
if( NULL != pnode->_right )
s_heap_pre_order_visit( pnode->_right, pvf );
}
void s_heap_in_order_visit( PHEAPNODE pnode, visit_func pvf )
{
if( NULL != pnode->_left )
s_heap_in_order_visit( pnode->_left, pvf );
pvf( pnode );
if( NULL != pnode->_right )
s_heap_in_order_visit( pnode->_right, pvf );
}
void s_heap_post_order_visit( PHEAPNODE pnode, visit_func pvf )
{
if( NULL != pnode->_left )
s_heap_post_order_visit( pnode->_left, pvf );
if( NULL != pnode->_right )
s_heap_post_order_visit( pnode->_right, pvf );
pvf( pnode );
}
void s_heap_order_visit( PHEAPNODE pnode, visit_func pvf )
{
PQUEUE pqueue = NULL;
PHEAPNODE p = NULL;
if( NULL == pnode || NULL == pvf )
return;
pqueue = queue_create();
if( NULL == pqueue )
return;
queue_enqueue( pqueue, pnode );
while( !queue_empty(pqueue) ) {
p = queue_dequeue(pqueue);
if( NULL == p )
break;
pvf( p );
queue_enqueue( pqueue, p->_left );
queue_enqueue( pqueue, p->_right );
}
queue_destroy( pqueue );
}
PHEAPNODE s_heap_find_insert_pos( PHEAP pheap )
{
PQUEUE pqueue = NULL;
PHEAPNODE ret = NULL;
PHEAPNODE p = NULL;
if( NULL == pheap || NULL == pheap->_root )
return NULL;
pqueue = queue_create();
if( NULL == pqueue )
return NULL;
queue_enqueue( pqueue, pheap->_root );
while( !queue_empty(pqueue) ) {
p = queue_dequeue(pqueue);
if( NULL == p )
break;
if( NULL == p->_left ) {
ret = p;
break;
}
else if( NULL == p->_right ) {
ret = p;
break;
}
else {
queue_enqueue( pqueue, p->_left );
queue_enqueue( pqueue, p->_right );
}
}
queue_destroy( pqueue );
return ret;
}
PHEAPNODE s_heap_find_last_node( PHEAP pheap )
{
PQUEUE pqueue = NULL;
PHEAPNODE pret = NULL;
PHEAPNODE p = NULL;
if( NULL == pheap || NULL == pheap->_root )
return NULL;
pqueue = queue_create();
if( NULL == pqueue )
return NULL;
queue_enqueue( pqueue, pheap->_root );
while( !queue_empty(pqueue) ) {
p = queue_dequeue(pqueue);
if( NULL == p )
break;
else
pret = p;
queue_enqueue( pqueue, p->_left );
queue_enqueue( pqueue, p->_right );
}
queue_destroy( pqueue );
return pret;
}
PHEAPNODE s_heap_find_data( PHEAPNODE pnode, Data data )
{
PHEAPNODE pret = NULL;
if( NULL == pnode )
return NULL;
if( pnode->_data == data )
return pnode;
pret = s_heap_find_data( pnode->_left, data );
if( NULL == pret )
pret = s_heap_find_data( pnode->_right, data );
return pret;
}
uint s_heap_node_count( PHEAPNODE pnode )
{
if( NULL == pnode )
return 0;
return s_heap_node_count( pnode->_left ) + s_heap_node_count( pnode->_right ) + 1;
}
测试代码:
#include "../heap/heap.h"
#include <iostream>
#pragma comment( lib, "../bin/heap.lib" )
void visit( PHEAPNODE pnode )
{
if( NULL != pnode )
std::cout << pnode->_data << " ";
}
int main( void )
{
PHEAP pheap = heap_create( HEAP_MINIMUM );
heap_insert( pheap, 54 );
heap_insert( pheap, 27 );
heap_insert( pheap, 35 );
heap_insert( pheap, 99 );
heap_insert( pheap, 890 );
heap_insert( pheap, 2 );
heap_insert( pheap, 34865 );
uint count = heap_node_count( pheap );
if( count > 0 ) {
Data *pdata = new Data[count];
heap_to_array( pheap, pdata, count );
for( uint i = 0; i < count; i++ )
std::cout << pdata[i] << " ";
std::cout << std::endl;
delete []pdata;
}
heap_pre_order_visit( pheap, visit ); std::cout << std::endl;
heap_in_order_visit( pheap, visit ); std::cout << std::endl;
heap_post_order_visit( pheap, visit ); std::cout << std::endl;
heap_remove( pheap );
heap_order_visit( pheap, visit ); std::cout << std::endl;
heap_remove( pheap );
heap_order_visit( pheap, visit ); std::cout << std::endl;
heap_destroy( pheap );
return 0;
}
运行结果: