这几天学习了堆,优先级队列和霍夫曼压缩算法,准备自己动手实现一下。今天先实现了堆,以备后用的同时也加深了对堆的理解。代码全部在CodeBlocks下测试通过。
头文件:
#ifndef _DATA_STRUCT_H
#define _DATA_STRUCT_H
#define ARRAY_OFFSET(a,size,offset) ((a) + (size)*(offset))
#define HEAP_BIG 0
#define HEAP_SMALL 1
typedef struct _heap_node
{
int pri;
}HEAP_NODE;
typedef struct _heap
{
int type;
int node_num;
int node_size;
int max_node_num;
void *array;
}HEAP;
#define HEAP_ENLARGE_NODE_NUM 20
#define HEAP_NODE_i(h,i) (ARRAY_OFFSET(h->array,h->node_size,i))
#define HEAP_NODE_PARENT(h,i) HEAP_NODE_i(h,(i-1)/2)
#define HEAP_ROOT(h) HEAP_NODE_i(h,0)
#define HEAP_LAST(h) HEAP_NODE_i(h,h->node_num-1)
#define HEAP_NODE_PRI(node) (((HEAP_NODE *)node)->pri)
#define HEAP_MAX_NODE_INDEX(h) (h->node_num - 1)
#define HEAP_NODE_VALID(h,i) (i < h->node_num)
#define HEAP_PARENT_NODE_INDEX(i) ((i-1)/2)
HEAP* heap_init(int type,int node_size,int init_node_num);
void heap_print(HEAP *h);
void heap_insert(HEAP *h,void *node);
int heap_get(HEAP *h,void *node);
#endif
堆实现代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "define.h"
#include "data_struct.h"
void heap_print(HEAP *h)
{
int i;
int print_num = 1,level = 0;
printf("node num=%d\n",h->node_num);
for(i = 0;i < h->node_num;i++)
{
HEAP_NODE *node = HEAP_NODE_i(h,i);
printf("N%d\t",node->pri);print_num--;
if(print_num == 0)
{
printf("\n");
level++;
print_num = 2*level;
}
}
printf("\n");
}
int heap_node_pri(HEAP *h,int node_i)
{
void *node = HEAP_NODE_i(h,node_i);
return HEAP_NODE_PRI(node);
}
static int heap_node_comp(HEAP *h,int na,int nb)
{
int pri_na = heap_node_pri(h,na);
int pri_nb = heap_node_pri(h,nb);
if(h->type == HEAP_BIG)
{
return pri_na > pri_nb ? na:nb;
}
else
return pri_na < pri_nb ? na:nb;
}
HEAP* heap_init(int type,int node_size,int init_node_num)
{
HEAP *heap = malloc(sizeof(HEAP));
heap->type = type;
heap->node_size = node_size;
heap->node_num = 0;
heap->max_node_num = init_node_num;
heap->array = malloc(heap->max_node_num * heap->node_size);
return heap;
}
static void heap_enlarge(HEAP *h,int enlarge_node_num)
{
printf("heap enlarge TBD\n");
return;
}
static BOOL heap_need_swap(int type,HEAP_NODE *node,HEAP_NODE *parent)
{
BOOL result = R_FALSE;
assert(node && parent);
if(type == HEAP_BIG)
result = node->pri > parent->pri;
else
result = node->pri < parent->pri;
return result;
}
static void heap_swap(int node_size,void *node,void *parent)
{
void *tmp = malloc(node_size);
memcpy(tmp,node,node_size);
memcpy(node,parent,node_size);
memcpy(parent,tmp,node_size);
return;
}
static void heap_swap_i(HEAP *h,int node_i,int parent_i)
{
return heap_swap(h->node_size,HEAP_NODE_i(h,node_i),HEAP_NODE_i(h,parent_i));
}
static BOOL heap_need_swap_i(HEAP *h,int node_i,int parent_i)
{
return heap_need_swap(h->type,HEAP_NODE_i(h,node_i),HEAP_NODE_i(h,parent_i));
}
/* adjust heap according to priority */
static void heap_adjust_insert(HEAP *h)
{
int node_i = h->node_num - 1;
HEAP_NODE *node = HEAP_NODE_i(h,node_i);
while(node != HEAP_ROOT(h))
{
HEAP_NODE *node_parent = HEAP_NODE_PARENT(h,node_i);
int parent_node_i = HEAP_PARENT_NODE_INDEX(node_i);
if(heap_need_swap(h->type,node,node_parent))
{
heap_swap(h->node_size,node,node_parent);
node_i = parent_node_i;
node = HEAP_NODE_i(h,node_i);
}
else
break;
}
return;
}
void heap_insert(HEAP *h,void *node)
{
if(h->node_num >= h->max_node_num)
heap_enlarge(h,HEAP_ENLARGE_NODE_NUM);
void *array_p = HEAP_NODE_i(h,h->node_num);
memcpy(array_p,node,h->node_size);
h->node_num++;
heap_adjust_insert(h);
return;
}
void heap_adjust_node(HEAP *h,int node_i)
{
int node_left_i = 2*node_i + 1,node_right_i = 2*node_i + 2;
BOOL l_valid,r_valid;
int node_selected = -1;
l_valid = HEAP_NODE_VALID(h,node_left_i);
r_valid = HEAP_NODE_VALID(h,node_right_i);
if(l_valid && r_valid)
node_selected = heap_node_comp(h,node_left_i,node_right_i);
else if(l_valid)
node_selected = node_left_i;
else if(r_valid)
node_selected = node_right_i;
if(node_selected != -1 && heap_need_swap_i(h,node_selected,node_i))
{
heap_swap_i(h,node_selected,node_i);
heap_adjust_node(h,node_selected);
}
return;
}
int heap_get(HEAP *h,void *node)
{
void *root_node = HEAP_ROOT(h);
void *last_node = HEAP_LAST(h);
if(h->node_num <= 0)
{
printf("heap is empty\n");
return -1;
}
else if(h->node_num ==1)
memcpy(node,root_node,h->node_size);
else if(h->node_num > 1)
{
memcpy(node,root_node,h->node_size);
memcpy(root_node,last_node,h->node_size);
}
h->node_num--;
if(h->node_num > 1)
heap_adjust_node(h,0);
return 0;
}
测试代码:
typedef struct _test_heap_node
{
HEAP_NODE node;
int stuff;
}TEST_HEAP_NODE;
void heap_test(void)
{
TEST_HEAP_NODE test_node;
HEAP *test_heap = heap_init(HEAP_SMALL,sizeof(TEST_HEAP_NODE),50);
test_node.node.pri = 5;
heap_insert(test_heap,&test_node);
test_node.node.pri = 7;
heap_insert(test_heap,&test_node);
test_node.node.pri = 1;
heap_insert(test_heap,&test_node);
test_node.node.pri = 3;
heap_insert(test_heap,&test_node);
test_node.node.pri = 2;
heap_insert(test_heap,&test_node);
test_node.node.pri = 8;
heap_insert(test_heap,&test_node);
test_node.node.pri = 9;
heap_insert(test_heap,&test_node);
test_node.node.pri = 13;
heap_insert(test_heap,&test_node);
test_node.node.pri = 2;
heap_insert(test_heap,&test_node);
test_node.node.pri = 6;
heap_insert(test_heap,&test_node);
test_node.node.pri = 4;
heap_insert(test_heap,&test_node);
heap_print(test_heap);
while(test_heap->node_num > 0)
{
heap_get(test_heap,&test_node);
printf("get node pri=%d\n",test_node.node.pri);
}
return;
}