C++模板实现堆

本文介绍了一种使用数组实现最大堆的方法,并详细展示了堆的插入与删除操作的具体步骤。通过维护堆的特性,确保每次操作后堆依然保持有序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆是一种特殊类型的二叉树,具有以下两个性质:
1. 每个节点的值大于/小于(最大堆/最小堆)等于其每个子节点的值
2. 该数完全平衡,最后一层的叶子都处于最左侧的位置

本文以最大堆为例子,实现堆的插入与删除操作.其中,堆的插入操作总是在最后的位置,删除操作总是在开头的位置.有些与队列的先进先出相似.
代码实现如下:
其中,利用数组来实现堆,数组的下标天然的可以对应堆的层次结构.若父节点下标为i,则左右子节点下标必然为2*i+1与2*i+2.
堆的插入总是在最后位置,插入后,对该位置进行上移交换,直到满足堆特性为止.删除时,总是删除根节点数据,然后将最后节点数据放入根节点,从根节点开始做向下交换,直到满足堆特性为止.

#ifndef _HEAP_H_
#define _HEAP_H_

#include "Constant.h"


template <class T>
struct HeapNode
{
    T data;                 //data
};


template <class T, unsigned int capacity>
class Heap
{
public:
    Heap();
    ~Heap();
    void AddElem(T value);
    void deleteElem(T &value);
    bool isFull();
    bool isEmpty();
private:
    HeapNode<T>** heapArray;
    unsigned int elemNum;
};

#endif
#include "Heap.h"

template <class T, unsigned int capacity>
Heap<T, capacity>::Heap()
{
    elemNum = 0;
    heapArray = new HeapNode<T>*[capacity];
}

template <class T, unsigned int capacity>
Heap<T, capacity>::~Heap()
{
    if (elemNum > 0)
    {
        for (int i = 0; i < elemNum; i++)
        {
            delete heapArray[i];
            heapArray[i] = NULL;
        }
    }
    if (NULL != heapArray)
    {
        delete[] heapArray;
        heapArray = NULL;
    }
    elemNum = 0;
}

template <class T, unsigned int capacity>
bool Heap<T, capacity>::isEmpty()
{
    bool result = false;
    if (0 == elemNum)
    {
        result = true;
    }
    else
    {
        result = false;
    }
    return result;
}

template <class T, unsigned int capacity>
bool Heap<T, capacity>::isFull()
{
    bool result = false;
    if (capacity == elemNum)
    {
        result = true;
    }
    else
    {
        result = false;
    }
    return result;
}

template <class T, unsigned int capacity>
void Heap<T, capacity>::AddElem(T value)
{
    if (isFull())
    {
        //Do nothing
    }
    else
    {
        HeapNode<T>* node = new HeapNode<T>();
        node->data = value;
        if (isEmpty())
        {
            heapArray[0] = node;
            elemNum++;
        }
        else
        {
            heapArray[elemNum] = node;
            int parentIndex = (elemNum - 1) / 2;
            int childIndex = elemNum;
            while (parentIndex >= 0)   //has parent
            {
                bool hasSwap = false;
                if (heapArray[childIndex]->data > heapArray[parentIndex]->data)
                {
                    int temp = heapArray[parentIndex]->data;
                    heapArray[parentIndex]->data = heapArray[childIndex]->data;
                    heapArray[childIndex]->data = temp;
                    hasSwap = true;
                }
                if (!hasSwap)
                {
                    break;
                }
                else
                {
                    childIndex = parentIndex;
                    parentIndex = (parentIndex - 1) / 2;
                }
            }
            elemNum++;
        }
    }
    return;
}

template <class T, unsigned int capacity>
void Heap<T, capacity>::deleteElem(T& value)
{
    if (isEmpty())
    {
        //Do nothing
    }
    else
    {
        value = heapArray[0]->data;
        //Copy last value to root, delete last memory
        heapArray[0]->data = heapArray[elemNum - 1]->data;
        delete heapArray[elemNum - 1];
        heapArray[elemNum - 1] = NULL;
        elemNum--;
        //move deap
        int index = 0;

        while (index * 2 + 1 < elemNum)
        {
            bool hasSwap = false;
            if (index * 2 + 2 < elemNum)  //Both has left and right
            {
                //compare 3 elem, index, index*2+1 & index*2+2
                if (heapArray[index * 2 + 1]->data > heapArray[index * 2 + 2]->data)   //Left is big
                {
                    if (heapArray[index]->data < heapArray[index * 2 + 1]->data)
                    {
                        //swap
                        int temp = heapArray[index]->data;
                        heapArray[index]->data = heapArray[index * 2 + 1]->data;
                        heapArray[index * 2 + 1]->data = temp;
                        hasSwap = true;
                        index = index * 2 + 1;
                    }
                    else
                    {
                        break;
                    }
                }
                else  //Right is big
                {
                    if (heapArray[index]->data < heapArray[index * 2 + 2]->data)
                    {
                        //swap
                        int temp = heapArray[index]->data;
                        heapArray[index]->data = heapArray[index * 2 + 2]->data;
                        heapArray[index * 2 + 2]->data = temp;
                        hasSwap = true;
                        index = index * 2 + 2;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            else  //only has left
            {
                //compare 2 elem, index & index*2+1, index*2+1 must leaf node, after compare, no need loop
                if (heapArray[index]->data < heapArray[index * 2 + 1]->data)
                {
                    int temp = heapArray[index]->data;
                    heapArray[index]->data = heapArray[index * 2 + 1]->data;
                    heapArray[index * 2 + 1]->data = temp;
                    break;
                }
                else
                {
                    break;
                }
            }
            if (!hasSwap)
            {
                break;
            }
        }
    }

    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值