堆的定义:

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;
}

运行结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值