堆的C语言实现

  这几天学习了堆,优先级队列和霍夫曼压缩算法,准备自己动手实现一下。今天先实现了堆,以备后用的同时也加深了对堆的理解。代码全部在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;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值