heap实现

//STL提供的是Max heap,使用vector作为底部容器
//push_heap算法:首先将元素放到堆所对应的数组的末端,然后从该节点开始向上调整,
//若当前结点键值比父结点大,则兑换位置,如此一直上溯,直到不需对换或直到根节点为止
template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last)
{
    //该函数被调用时,新元素已置于底部容器的最末端
    _push_heap_aux(firsst, last, distance_type(first), value_type(first));
}

template <class RandomAccessIterator ,class Distance,class T>
inline void _push_heap_aux(RandomAccessIterator first, RandomAccessIterator last, Distance*, T*)
{
    _push_heap(first, Distance((last - first) - 1), Distance(0), T(*(last - 1)));
}

template <class RandomAccessIterator, class Distance, class T>
//first是根节点的迭代器,holeIndex是当前结点下标,topIndex是根节点下标,value是要调整的元素的值
void _push_heap(RandomAccessIterator first, Distance holeIndex, Distance topIndex, T value)
{
    Distance parent = (holeIndex - 1);//父节点下标
    while (holeIndex > topIndex&&*(first + parent) < value)
    {
        *(first + holeIndex) = *(first + parent);
        holeIndex = parent;
        parent = (holeIndex - 1) / 2;
    }
    *(first + holeIndex) = value;
}

//pop_heap算法:将最下层最右边的叶节点(即底层容器中最末端元素)替换根节点,然后向下调整
//pop_heap后,最大元素只是被置放于底部容器的最尾端,尚未被取走
template <class RandomAccessIterator ,class Distance,class T>
//holeIndex初始化为0,是根节点的位置,本算法先一直向下调整到叶节点,然后可能需要向上调整
//实际上没必要,只需要当当前结点比左右孩子结点的值都大时就可以停止调整了
void _adjust_heap(RandomAccessIterator first, Distance holeIndex, Distance len, T value)
{
    Distance topIndex = holeIndex;
    Distance secondChild = 2 * holeIndex + 2;//右子结点
    while (secondChild < len)
    {
        if (*(first + secondChild) < *(first + secondChild - 1))
            secondChild--;
        *(first + holeIndex) = *(first = secondChild);
        holeIndex = secondChild;
        secondChild = 2 * (secondChild + 1);
    }
    if (secondChild == len)//没有右子结点,只有左子结点
    {
        *(first + holeIndex) = *(first + secondChild - 1);
        holeIndex = secondChild - 1;
    }
    _push_heap(first, holeIndex, topIndex, value);
}

//sort_heap算法:连续调用pop_heap即可
//排序之后,原来的heap就不再符合heap的特征了
template <class RandomAccessIterator>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last)
{
    while (last - first > 1)
        pop_heap(first, last--);
}

//make_heap算法:从最后一个非叶节点开始,每个非叶节点都向下调整
template <class RandomAccessIterator,class T,class Distance>
void _make_heap(RandomAccessIterator first, RandomAccessIterator last, T*, Distance*)
{
    if (last - first < 2)
        return;
    Distance len = last - first;
    Distance parent = (len - 2) / 2;

    while (ture)
    {
        _adjust_heap(first, parent, len, T(*(first + parent)));
        if (parent == 0)
            return;
        parent--;
    }
}

 

posted @ 2015-01-16 14:43  合唱团abc  阅读(331)  评论(0编辑  收藏  举报