二叉堆

BinaryHeap.h文件

#ifndef BINARY_HEAP_H
#define BINARY_HEAP_H

namespace ghost{

template<typename A>
void MinHeapShiftUp(A& array, const size_t size, size_t n/*umber(not index)*/)
{
    if (0 == size)
    {
        // array为空
        return;
    }
    if (size < n || 2 > n)
    {
        // n超出有效区间,或者没有父节点
        return;
    }

    auto temp = array[n-1];
    size_t holeN = n; // 建立空洞

    while (true)
    {
        /// 测试父节点
        size_t pn = holeN / 2; // 父节点number
        if (0 == pn)
        {
            // pn超出有效区间
            break;
        }
        if (array[pn-1] > temp)
        {
            // 父节点较大下移,将空洞移动到父节点位置
            array[holeN-1] = array[pn-1];
            holeN = pn;
        }
        else
        {
             // 已经找到位置
            break;
        }
    }
    if (holeN != n)
    {
        // 空洞位置发生变化,将节点放入空洞
        array[holeN-1] = temp;
    }
}

template<typename A>
void MinHeapShiftDown(A& array, const size_t size, size_t n/*umber(not index)*/)
{
    if (0 == size)
    {
        // array为空
        return;
    }
    if (size <= n || 0 == n)
    {
        // n超出有效区间,或者没有任何子节点
        return;
    }

    auto temp = array[n-1];
    size_t holeN = n; // 建立空洞

    while (true)
    {
        /// 从空洞位置开始
        size_t parentN = holeN;
        auto* pMin = &temp;

        /// 测试左子节点
        size_t ln = 2 * parentN; // 左子节点number
        if (size < ln)
        {
            // ln超出有效区间
            break;
        }
        if (array[ln-1] < *pMin)
        {
            // 左子节点较小,将空洞移动到左子节点位置
            holeN = ln;
            pMin = &array[ln-1];
        }

        /// 测试右子节点
        size_t rn = ln + 1; // 右子节点number
        if (size >= rn)
        {
            if (array[rn-1] < *pMin)
            {
                // 右子节点较小,将空洞移动到右子节点位置
                holeN = rn;
                pMin = &array[rn-1];
            }
        }

        if (holeN == parentN/*&temp == pMin*/)
        {
            // 已经找到位置
            break;
        }
        else
        {
            // 较小节点上移
            array[parentN-1] = /*array[holeN-1]*/*pMin;
        }
    }
    if (holeN != n)
    {
        // 空洞位置发生变化,将节点放入空洞
        array[holeN-1] = temp;
    }
}

template<typename A>
void InitMinHeap(A& array, const size_t size)
{
    for (size_t n = size/2; n > 0; --n)
 	{
 		MinHeapShiftDown(array, size, n);
 	}
}

} // namespace ghost

#endif // BINARY_HEAP_H

main.cpp文件

#include "FileDescriptor.h"
#include "ResizableBuffer.h"
#include "BinaryHeap.h"
#include <iostream>
#include <cassert>

template<typename A>
void PrintArray(A& array, const size_t size)
{
    if (0 < size)
    {
        size_t endIndex = size - 1;
        for (size_t i = 0; i < endIndex; ++i)
        {
            std::cout<<array[i]<<",";
        }
        std::cout<<array[endIndex];
    }
    std::cout<<std::endl;
}

int main()
{
    std::cout<<"\n小根堆初始化:\n"<<std::endl;

    int array[] = {9,8,7,6,5,4,3,2,1,0};
 	size_t arraySize = sizeof(array)/sizeof(array[0]);
 	PrintArray(array, arraySize);

 	ghost::InitMinHeap(array, arraySize);

 	std::cout<<"\n小根堆push模拟:\n"<<std::endl;

    for (int i = 0; (size_t)i < arraySize; ++i)
    {
        /// 因为测试用数组定长,所以我利用每次改变数组最后一个元素的值来模拟push操作(push操作就是先将元素插入到末尾,然后上滤)
        array[arraySize-1] = -(i);
        PrintArray(array, arraySize);
        ghost::MinHeapShiftUp(array, arraySize, arraySize);
        std::cout<<"->";
        PrintArray(array, arraySize);
    }

    std::cout<<"\n小根堆pop模拟:\n"<<std::endl;

    for (int i = arraySize-1; i >= 0; --i)
    {
        /// 因为测试用数组定长,所以我利用每次将数组最后一个元素的值复制到数组头,然后将最后一个元素置0
        ///(pop操作就是先将数组头元素临时保存,然后将最后一个元素提道数组头,最后从数组头开始下滤)
        PrintArray(array, arraySize);
        array[0] = array[i];
        array[i] = 0;
        ghost::MinHeapShiftDown(array, i, 1);
        std::cout<<"->";
        PrintArray(array, i);
    }

 	std::cin.get();

    ghost::FileDescriptor testFD(0);
    ghost::ResizableBuffer<int> testRB(1);
    std::cout << "Hello world!" << std::endl;
    return 0;
}
posted @ 2011-11-25 15:38  Evil.Ghost  阅读(451)  评论(0编辑  收藏  举报