二叉堆的实现

用c实现小顶堆,堆元素类型问int。最大容量为100。随后的文章我将会用c++模板技术改写这个程序,使他能够适应更多数据类型。

这篇文章主要是呈现C代码,不会对原来过多解释。二叉堆原理详见我的博客http://blog.csdn.net/bdss58/article/details/40742817

首先定义堆的数据结构,堆元素用数组存储:

// 堆结构体,元素类型暂定int
typedef struct
{
    // 当前堆中元素的个数
    int heap_size;
    // 用数组存储元素
    int values[MAX_ITEMS];
}int_heap;

还有定义初始化函数,删除元素函数和添加元素函数。

上面的一些定义就可以构成一个完整的头文件了,heap.h:

#ifndef HEAP_H
#define HEAP_H

// 最多可以存储元素的个数
#define MAX_ITEMS 100

// 堆结构体,元素类型暂定int
typedef struct
{
    // 当前堆中元素的个数
    int heap_size;
    // 用数组存储元素
    int values[MAX_ITEMS];
}int_heap;

// 初始化堆
void init_heap(int_heap* root);
// 取得堆的首元素,并删除之
int get_first_value(int_heap* root);
// 往堆中加入新元素
void add_value(int_heap* root,int value);

#endif // HEAP_H

接下来就该实现头文件中定义的函数了。

为了实现添加和删除,需要一些辅助函数。

sift_up()"提升函数”,当从堆中添加元素时,用它来调整堆;

// sift_up function “上升”调整堆
void sift_up(int_heap* root,int index)
{
    assert(root!=NULL);
    int parent_index=PARENT(index);
    assert(parent_index>=0);
    if(index==0)
    {
        return;
    }
    if(root->values[parent_index]>root->values[index])
    {
        swap_values(root,parent_index,index);
        if(parent_index!=0)
        {
            sift_up(root,parent_index);
        }
    }
}

sift_down“下沉函数”,当从堆中删除元素时,用它来调整堆。

// sift_down function “下潜”调整堆
void sift_down(int_heap* root,int index)
{
    int left_child=LEFT_CHILD(index);
    int right_child=RIGHT_CHILD(index);
    if(left_child>root->heap_size)
    {
        // 说明没有左右孩子,终结条件,返回
        return;
    }
    if(right_child>=root->heap_size)
    {
        // 说明只有左孩子
        if(root->values[index]>root->values[left_child])
        {
            swap_values(root,index,left_child);
            sift_down(root,left_child);
        }
    }
    else
    {
        // 接下来说明左右孩子都有
        if(root->values[index]>root->values[left_child] || root->values[index]>root->values[right_child])
        {
            int min_index;
            if(root->values[left_child]>root->values[right_child])
            {
                min_index=right_child;
            }
            else
            {
                min_index=left_child;
            }
            swap_values(root,index,min_index);
            sift_down(root,min_index);
        }
    }
}

整个heap.c文件:

/**
  * 实现小顶堆
  * 作者:bdss58
  * BSD 许可证
  * 你可以拿去随便修改使用
  * */

#include <assert.h>
#include <stdlib.h>

#include "heap.h"

// 注意加括号
#define LEFT_CHILD(index) (2*(index)+1)
#define RIGHT_CHILD(index) (2*(index)+2)
#define PARENT(index) (((index)-1)/2)

// swap_values function 交换两个变量的值
void swap_values(int_heap* root,int i,int j)
{
    int temp;
    // 检查参数合法性
    assert(root != NULL);
    assert(i>=0 && i<root->heap_size);
    assert(j>=0 && j<root->heap_size);
    assert(i != j);
    temp=root->values[i];
    root->values[i]=root->values[j];
    root->values[j]=temp;

}

// sift_down function “下潜”调整堆
void sift_down(int_heap* root,int index)
{
    int left_child=LEFT_CHILD(index);
    int right_child=RIGHT_CHILD(index);
    if(left_child>root->heap_size)
    {
        // 说明没有左右孩子,终结条件,返回
        return;
    }
    if(right_child>=root->heap_size)
    {
        // 说明只有左孩子
        if(root->values[index]>root->values[left_child])
        {
            swap_values(root,index,left_child);
            sift_down(root,left_child);
        }
    }
    else
    {
        // 接下来说明左右孩子都有
        if(root->values[index]>root->values[left_child] || root->values[index]>root->values[right_child])
        {
            int min_index;
            if(root->values[left_child]>root->values[right_child])
            {
                min_index=right_child;
            }
            else
            {
                min_index=left_child;
            }
            swap_values(root,index,min_index);
            sift_down(root,min_index);
        }
    }
}

// sift_up function “上升”调整堆
void sift_up(int_heap* root,int index)
{
    assert(root!=NULL);
    int parent_index=PARENT(index);
    assert(parent_index>=0);
    if(index==0)
    {
        return;
    }
    if(root->values[parent_index]>root->values[index])
    {
        swap_values(root,parent_index,index);
        if(parent_index!=0)
        {
            sift_up(root,parent_index);
        }
    }
}

void init_heap(int_heap *root)
{
    assert(root != NULL);
    root->heap_size=0;
}

// 取得第一个元素,并删除之
int get_first_value(int_heap *root)
{
    int result;
    assert(root != NULL);
    assert(root->heap_size>0);

    result=root->values[0];
    root->heap_size--;

    if(root->heap_size!=0)
    {
        root->values[0]=root->values[root->heap_size];
        sift_down(root,0);
    }

    return result;
}


void add_value(int_heap *root, int value)
{
    assert(root != NULL);
    // 保证已经初始化堆
    assert(root->heap_size>=0);

    assert(root->heap_size<MAX_ITEMS);
    root->values[root->heap_size]=value;
    root->heap_size++;

    // sift_up function “上升”调整
    if(root->heap_size-1 != 0)
    {
        sift_up(root,root->heap_size-1);
    }
}

这时,可以在main.c中做测试了:

#include <stdio.h>
#include <stdlib.h>

#include "heap.h"

int main(void)
{
    int_heap h;
    init_heap(&h);
    int i;
    srand(11);

    // 按最大容量将heap填满
    for(i=0;i<MAX_ITEMS;i++)
    {
        add_value(&h,rand()%1000);
    }

    int lastval=get_first_value(&h);
    printf("Value 0=%d\n",lastval);

    for(i=1;i<MAX_ITEMS;i++)
    {
        int val=get_first_value(&h);
        printf("Value %d=%d\n",i,val);
        if(val<lastval)
        {
            printf("out error\n");
        }
        lastval=val;
    }

    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值