14、堆

来源:互联网 发布:nginx域名解析 编辑:程序博客网 时间:2024/05/22 07:05

1、用途:快速找到最大或最小元素,每一层的父节点始终大于或小于左右节点,左右节点之间没有关系。最底层最右端的节点就是最后一个节点。

2、节点成S行自上而下,自左向右顺序编号。元素对应在数组当中。若父节点编号为n,那么左右节点分别为2n+1,2n+2。可以随机访问,虽然属于二叉树,但是不用指针把每个节点串起来体现节点之间的关系。

有些定义放在xxxx.c中说明他们不是公共接口,可以访问的公共接口放在xxxx.h文件中。

3、数据结构

typedef struct _HEAP_H{    int size;    void **tree;    void (*destroy)(void *data);    int (*compare)(void *key1, void *key2);}Heap;

4、初始化堆,释放堆

void heap_init(Heap *tree, void (*destroy)(void *data), int (*compare)(void *key1, void *key2)){    tree->size = 0;    tree->tree = NULL;    tree->destroy = destroy;    tree->compare = compare;    return;}void heap_destroy(Heap *tree){    int i;    if(tree->destroy != NULL)    {        for(i = 0; i < heap_size(tree); i++)        {            tree->destroy(tree->tree[i]);        }    }    free(tree->tree);    memset(tree, 0, sizeof(Heap));    return;}

5、向堆中插入元素

int heap_insert(Heap *heap, const void *data){    void *temp;    int ipos, ppos;    //动态扩展数组    if(( temp = (void **)realloc(heap->tree, (heap->size * sizeof(void *) + 1)) ) == NULL)        return -1;    else    {        heap->tree = temp;    }    //先把要插入的树存入尾部    heap->tree[heap_size(heap)] = (void *)data;    ipos = heap_size(heap);    ppos = heap_parent(ipos);    //父节点小,则一直和父节点进行交换    while(ipos > 0 && heap->compare(heap->tree[ppos], heap->tree[ipos]) < 0)    {        temp = heap->tree[ppos];        heap->tree[ppos] = heap->tree[ipos];        heap->tree[ipos] = temp;        ipos = ppos;        ppos = heap_parent(ipos);    }    heap->size++;    return 0;} 

6、删掉头部,即最大或最小的那个

//去掉头节点,重新排列 int heap_extract(Heap *heap, void **data){    void *save, *temp;    int ipos, lpos, rpos, mpos;    if(heap_size(heap) == 0)        return -1;    *data = heap->tree[0];//先把最后一个元素保存起来,在缩小空间    save = heap->tree[heap_size(heap) - 1];    if(heap_size(heap) - 1 > 0)    {        if((temp = (void **)realloc(heap->tree, (heap_size(heap) - 1) * sizeof(void *))) == NULL)            return -1;        else        {            heap->tree = temp;          }        heap->size--;    }     //如果size == 1,重新初始化     else    {        free(heap->tree);        heap->tree = NULL;        heap->size = 0;        return 0;     }    heap->tree[0] = save;   //最后一个元素移到顶部     ipos = 0;    while(1)    {        lpos = heap_left(ipos);        rpos = heap_right(ipos);        //左节点标号不能超过最大标号,且左节点大于父节点 ,用mpos保存大的那方         if((lpos < heap_size(heap)) && (heap->compare(heap->tree[lpos], heap->tree[ipos]) > 0))        {            mpos = lpos;        }        else         {            mpos = ipos;        }        if((rpos < heap_size(heap)) && heap->compare(heap->tree[rpos], heap->tree[ipos]) > 0)        {            mpos = rpos;        }        if(mpos == ipos)        {               break;//当前节点大于左右,结束循环         }        else        {            temp = heap->tree[mpos];            heap->tree[mpos] = heap->tree[ipos];            heap->tree[ipos] = temp;            ipos = mpos;//这里是标号,向下调整直到调整后的子树父节点大于左右        }    } }
原创粉丝点击