Chinaunix首页 | 论坛 | 博客
  • 博客访问: 449939
  • 博文数量: 73
  • 博客积分: 3593
  • 博客等级: 中校
  • 技术积分: 912
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-14 11:32
文章分类

全部博文(73)

文章存档

2013年(2)

2012年(20)

2011年(25)

2010年(12)

2009年(14)

分类: C/C++

2009-11-25 16:48:20

/* binheap.c
 * 二叉堆的结构属性:
 * 必须是一颗完成二叉树。这使得可以用数组来存取二叉堆,但数组大小需要预先估计好。
 * 二叉堆的堆序性:
 * 每个节点关键字的值必须不小于其父节点关键字的值。这使得根节点的关键字值总是最小。
 * nizqsut@163.com
 */

#include
#include

#include "binheap.h"
#include "fatal.h"

#define MIN_PQ_SIZE    (10)
#define MIN_DATA    (-32767) /* 哨兵 */
#define MAX_DATA    (32768)

struct bin_heap
{
    int capacity;
    int size;
    element_type *elements;
};

static int
is_empty( prior_queue h )
{
    return h->size == 0;
}

static int
is_full( prior_queue h )
{
    return h->size == h->capacity;
}

static prior_queue
initialize(int max_elements)
{
    prior_queue h;

    if (max_elements < MIN_PQ_SIZE)
        Error("Priority queue size is to small!");
    

    h = malloc( sizeof( struct bin_heap ) );
    if ( NULL == h)
        Error("Out of space!");

    /* 使用h->elements[0]作为哨兵,因此多分配的一个单元 */
    h->elements = malloc( (max_elements + 1)
                    * sizeof(element_type) );
    if ( NULL == h->elements){
        free(h);
        Error("Out of space!");
    }

    h->capacity = max_elements;
    h->size = 0;
    h->elements[0] = MIN_DATA;

    return h;
}

static void
make_empty(prior_queue h)
{
    h->size = 0;
}

static void
insert( element_type x, prior_queue h)
{
    int i;

    if ( is_full(h) )
        Error("Priority queue is full!");

    /*
    如果空穴的父节点的值比插入值大,则空穴往上移一层;
    否则将插入值填入空穴中。
    */
    for ( i =++h->size; h->elements[i/2] > x; i /= 2){
        h->elements[i] = h->elements[i/2];
    }
    h->elements[i] = x;
}

/*
    删除二叉堆的最小单元
    二叉堆的最小单元就是根节点,删除根节点后需要从子树中寻找一个节点
    来做为根节点。方法是将根节点处的空穴下沉,并将最后那个节点移到合适的空穴上。
*/
static element_type
delete_min( prior_queue h )
{
    int i, child;

    element_type min_element, last_element;

    if ( is_empty( h ) ){
        Error("Priority queue is empty!");
        return h->elements[0];
    }

    min_element = h->elements[1];
    last_element = h->elements[h->size--];

    for ( i = 1; i * 2 <= h->size; i = child ){
        child = i * 2;
        if ( child != h->size && h->elements[child + 1]
            < h->elements[child] )
            child++;

        if ( last_element > h->elements[child] ){
            h->elements[i] = h->elements[child];
        }else{
            break;
        }
    }

    h->elements[i] = last_element;

    return min_element;
}

static element_type
find_min(prior_queue h)
{
    if ( !is_empty(h) )
        return h->elements[1];

    Error("Priority queue is empty!");
    return h->elements[0];
}

static void destroy(prior_queue h)
{
    if ( h == NULL )
        return;

    free( h->elements );
    free( h );
}

static int
get_parent( int pos )
{
    return (pos & 1) ? ( (pos - 1) / 2 ) : ( pos / 2 );
}

/*
 * 降低指定位置关键字的值,根据新值重新调整二叉堆的
 * value 必须是正值!
 */
static int
decrease_key( int pos, int value, prior_queue h)
{
    int i;
    int parent;
    int new_element;

    if ( h == NULL || pos > h->size ){
        Error("Input parameter error!");
        return -1;
    }
   
    i = pos; // + 1;
    new_element = h->elements[i] - value;
   
    for (parent = get_parent(i);  parent > 0; parent = get_parent(i) ){
        if ( new_element < h->elements[parent])
            h->elements[i] = h->elements[parent];
        else
            break;
        i /= 2;
    }
    h->elements[i] = new_element;

    return 0;
}

/*
 * 删除指定位置的节点:
 *        通过先将该位置关键字值降到最小,令其位置调整到根节点上,
 *        在调用delete_min()删除之。
 */
static int
delete_element( int pos, prior_queue h )
{
    if ( decrease_key( pos, MAX_DATA, h) )
        return -1;

    delete_min( h );

    return 0;
}


/************    Next we test binary heap    ***************/

#define get_array_size(array)    ( sizeof(array) / sizeof(array[0]) )

void test_bin_heap(void)
{
    int i;
    int min_element;

    prior_queue h;
    element_type elements[] =
                {3, 12, 11, 8, 9, 6, 5,
                24, 1, 7, 13, 66, 28,
                10, 20, 15, 16, 22, 2};

    h = initialize(64);
    if ( NULL == h )
        return;

    for ( i = 0; i < get_array_size(elements); i++){
        insert(elements[i], h);
    }

    /* test for find_min() */
    min_element = find_min( h );

    /* test for delete_element() */
    delete_element(9, h);

    /* test for delete_min() */
    min_element = delete_min( h );
    min_element = find_min( h );

    destroy( h );
}

/****************************************************************************************************/

/* binheap.h */

#ifndef _BINHEAP_H_
#define _BINHEAP_H_

typedef int element_type;

struct bin_heap;
typedef struct bin_heap *prior_queue;

#endif
阅读(1551) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~