手写堆

堆是一种特殊的数据结构,它通常是一个可以被看做一棵树的数组对象。这个数组以二叉树的形式来维护。注意:这个二叉树必须是完全二叉树。

堆又分为小根堆和大根堆。顾名思义,小根堆就是每个父亲节点都小于等于其儿子节点;大根堆反之。

而数据用堆存储时并不是随着数组下标增大数据有序增大或减小,而是以下边的方式存储:

根节点下标=孩子下标/2
左孩子下表=根节点下标*2+1
右孩子下标=左孩子下标+1

虽说c++STL提供了优先队列这种东西,但手写堆也有其自己的好处,例如灵活性高,运行快等。

那么如何写堆呢?

首先堆应该在其性质不变的前提下,支持返回堆顶,删除堆顶,插入元素

返回堆顶:

int heap_top()
{
    return heap[1];
}

删除堆顶:

void heap_pop()
{
    heap[1]=heap[tot];
    tot--;
    now_x=1;
    while(1)
    {
        if((now_x<<1)>tot)
        break;
        if((now_x<<1)==tot)
        next_x=tot;
        else
        {
            if(heap[now_x<<1]<heap[(now_x<<1)+1])
            next_x=(now_x<<1);
            else
            next_x=(now_x<<1)+1;
        }
        if(heap[now_x]>heap[next_x])
        {
            swap(heap[now_x],heap[next_x]);
            now_x=next_x;
        }
        else
        break;
    }
}

插入元素:

void heap_add(int x)
{
    tot++;
    heap[tot]=x;
    now_x=tot;
    while(1)
    {
        if(heap[now_x]<heap[now_x>>1])
        {
            swap(heap[now_x],heap[now_x>>1]);
            now_x>>=1;
        }
        else
        break;
    }
}

维护原理:将父亲节点与子节点比较,若符合规则,则不变;否则交换它们两个的值。

posted @ 2018-03-04 02:39  Coool  阅读(480)  评论(0编辑  收藏  举报