码迷,mamicode.com
首页 > 其他好文 > 详细

基本数据结构之堆

时间:2015-07-13 22:28:39      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:

堆的定义

堆是一个完全二叉树或者近似的完全二叉树

堆的性质

  1. 父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
  2. 每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
堆的存储

一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2

堆的特点

插入元素和弹出堆顶元素的时间复杂度lg(n)

判断序列是不是堆

根据性质判断

比如输入序列15,30,22,93,52,71,89,15是根节点,可以看出满足性质,这是一个小根堆
                15
         30             22
    93       52    71        89

堆的C语言实现

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

//c++ 中的priority_queue就是一个堆

typedef int heap_elem; //堆的数据类型

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 堆的基本结构
 *  
 */
typedef struct heap
{
    int size; //实际元素个数
    int capacity;//堆的容量
    heap_elem* elements;//堆的存储数组
    int(*cmp)(const heap_elem*, const heap_elem*); //元素的比较函数
}heap;

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 创建一个堆
 * @param capacity 容量
 * @param cmp,小于返回-1,等于返回0,大于返回1,反过来是大根堆
 * @return 成功返回堆对象的指针,否则为nullptr
 *  
 */
heap* heap_create(const int capacity, int(*cmp)(const heap_elem*, const heap_elem*))
{
    heap* myheap = (heap*)malloc(sizeof(heap));

    myheap->size = 0;
    myheap->capacity = capacity;
    myheap->cmp = cmp;
    myheap->elements = (heap_elem*)malloc(capacity*sizeof(heap_elem));

    return myheap;
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 销毁堆
 * @param 
 * @return 无
 *  
 */
void heap_destory(heap* myheap)
{
    free(myheap->elements);
    free(myheap);
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 判断堆是否为空
 * @param 
 * @return 返回true 是空,否则false
 *  
 */
bool heap_empty(const heap* myheap)
{
    return myheap->size == 0;
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 堆的元素的个数
 * @param 
 * @return 返回元素的个数
 *  
 */
int heap_size(const heap* myheap)
{
    return myheap->size;
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 获取堆顶元素
 * @param 
 * @return 返回堆顶元素
 *  
 */

heap_elem heap_top(const heap* myheap)
{
    return myheap->elements[0];
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 小根堆的自上而下的筛选算法
 * @param start 开始的结点
 * @return
 *  
 */
void heap_sift_down(const heap* myheap, const int start)
{
    int i = start;
    int j;

    const heap_elem temp = myheap->elements[start];

    for (j = 2 * i + 1; j < myheap->size; j = 2 * j + 1)
    {
        if (j < myheap->size - 1 && myheap->cmp(&(myheap->elements[j]), &(myheap->elements[j + 1]))>0)
        {
            j++;//j指向两子女中的较小者
        }
        if (myheap->cmp(&temp, &(myheap->elements[j]))<=0)
        {
            break;
        }
        else
        {
            myheap->elements[i] = myheap->elements[j];
            i = j;
        }
    }
    myheap->elements[i] = temp;
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 小根堆自下而上的筛选算法
 * @param  start 起始位置
 * @return
 *  
 */
void heap_sift_up(const heap* myheap, const int start)
{
    int j = start;
    int i = (j - 1) / 2;
    const heap_elem temp = myheap->elements[start];

    while (j > 0)
    {
        if (myheap->cmp(&(myheap->elements[i]), &temp) <= 0)
        {
            break;
        }
        else
        {
            myheap->elements[j] = myheap->elements[i];
            j = i;
            i = (i - 1) / 2;
        }
    }
    myheap->elements[j] = temp;
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 添加元素
 * @param 
 * @return
 *  
 */
void heap_push(heap* myheap, const heap_elem x)
{
    //堆已满,重新分配内存
    if (myheap->size == myheap->capacity)
    {
        heap_elem* temp =(heap_elem*)realloc(myheap->elements, myheap->capacity * 2 * sizeof(heap_elem));
        myheap->elements = temp;
        myheap->capacity *= 2;
    }
    myheap->elements[myheap->size] = x;
    myheap->size++;

    heap_sift_up(myheap, myheap->size - 1);
}


/**
* @author 韦轩
* @time 2015/07/13
* @brief 弹出栈顶元素
* @param
* @return
*
*/
void heap_pop(heap* myheap)
{
    myheap->elements[0] = myheap->elements[myheap->size - 1];
    myheap->size--;

    heap_sift_down(myheap, 0);
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 基本数据类型的比较
 * @param 
 * @return
 *  
 */
int cmp(const int* data1, const int* data2)
{
    const int ret = *data1 - *data2;
    if (ret < 0)
        return -1;
    else if (ret > 0)
        return 1;
    else
        return 0;
}

/**
 * @author 韦轩
 * @time 2015/07/13
 * @brief 打印堆,默认是int 
 *  
 */
void heap_print(const heap* myheap)
{
    if (myheap == NULL)
        return;
    for (int i = 0; i < myheap->size; i++)
    {
        printf_s("%d\t", myheap->elements[i]);
    }
}
int main()
{
    heap* myheap = heap_create(6, cmp);

    heap_push(myheap, 10);
    heap_push(myheap, 3);
    heap_push(myheap, 2);
    heap_push(myheap, 5);
    heap_push(myheap, 1);

    puts("初始...\n");
    heap_print(myheap);

    puts("插入100,20...\n");
    heap_push(myheap, 100);
    heap_push(myheap,20);

    heap_print(myheap);

    puts("删除堆顶元素...\n");

    heap_pop(myheap);

    heap_print(myheap);

    heap_destory(myheap);

    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

基本数据结构之堆

标签:

原文地址:http://blog.csdn.net/weiyongxuan/article/details/46867855

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!