如何实现最大堆

How to implement a max heap

本文关键字:实现 何实现      更新时间:2023-10-16

我有代码来构建一个最大堆,但它一直返回我给它的相同数组。我敢肯定这是个小错误,但我似乎想不出来。如有任何帮助,不胜感激。

可编译的示例代码:

#include <iostream>
#include <cmath>
class Heaparr {
public:
    Heaparr();
    void insert(int da);
    int getLeft(int i) { return 2 * i; }
    int getRight(int i) { return (2 * i) + 1; }
    int getParent(int i) { return i / 2; }
    int getMax() { return maxHeap[0]; }
    void print();
    void reheap(int num);
    void makeArray();
    void Build_Max_Heap(int maxHeap[], int heap_size);
    void Max_Heapify(int heapArray[], int i, int heap_size);
    void heapSort(int heapArray[]);
private:
    int size;
    int* maxHeap;
    int index;
    int i;
};
Heaparr::Heaparr() {
    maxHeap = nullptr;
    size = 0;
}
void Heaparr::insert(int da) {
    size++;
    int* tmp = new int[size];
    for (int i = 0; i < size - 1; i++) {
        tmp[i] = maxHeap[i];
    }
    tmp[size - 1] = da;
    delete[] maxHeap;
    maxHeap = tmp;
}
void Heaparr::heapSort(int maxHeap[]) {
    int heap_size = size;
    int n = size;
    int temp;
    Build_Max_Heap(maxHeap, heap_size);
    for (int i = n - 1; i >= 1; i--) {
        temp = maxHeap[0];
        maxHeap[0] = maxHeap[i];
        maxHeap[i] = temp;
        heap_size = heap_size - 1;
        Max_Heapify(maxHeap, 0, heap_size);
    }
    for (int i = 0; i < 8; i++) {
        std::cout << maxHeap[i] << std::endl;
    }
}
void Heaparr::Build_Max_Heap(int maxHeap[], int heap_size) {
    int n = size;
    for (int i = floor((n - 1) / 2); i >= 0; i--) {
        Max_Heapify(maxHeap, i, heap_size);
    }
    return;
}
void Heaparr::Max_Heapify(int heapArray[], int i, int heap_size) {
    // int n = size;
    int largest = 0;
    int l = getLeft(i);
    int r = getRight(i);
    if ((l <= heap_size) && (heapArray[l] > heapArray[i])) {
        largest = l;
    } else {
        largest = i;
    }
    if ((r <= heap_size) && (heapArray[r] > heapArray[largest])) {
        largest = r;
    }
    int temp;
    if (largest != i) {
        temp = heapArray[i];
        heapArray[i] = heapArray[largest];
        heapArray[largest] = temp;
        Max_Heapify(heapArray, largest, heap_size);
    }
    return;
}
int main(int argc, char* argv[]) {
    int hArray[8] = {5, 99, 32, 4, 1, 12, 15, 8};
    Heaparr t;
    t.heapSort(hArray);
    for (auto v : hArray) {
        std::cout << v << ", ";
    }
    std::cout << std::endl;
}

我做了一些固定的代码(我尽量不改变太多的原始代码):

  • getLeft, getRightgetParent公式错误(例如:当i == 0子节点必须为1和2,而您的代码为0和1)。返回类型也错误,应该是int(数组索引)。
  • 您是否在所有方法中接收int[],除了insertmember variable中的double[],将所有更改为int[],如果您需要将所有更改回
  • 在数组中使用std::swap交换值
  • 增加数组的长度到heapSort(在方法内部这个信息丢失,需要通过参数传递)。

指出:

  • 我不知道你在哪里使用成员变量maxHeap,因为除了getMaxinsert之外的所有方法都使用参数传递的数组,而不是成员变量(也许你应该在构造函数或heapSort方法中初始化)。
  • 尝试使用std::vector代替C Array
代码:

#include <iostream>
#include <cmath>
class Heaparr {
public:
    Heaparr();
    void insert(int da);
    int getLeft(int i) { return 2 * i + 1; }
    int getRight(int i) { return 2 * i + 2; }
    int getParent(int i) { return (i - 1) / 2; }
    int getMax() { return maxHeap[0]; }
    void print();
    void reheap(int num);
    void makeArray();
    void Build_Max_Heap(int heapArray[], int heap_size);
    void Max_Heapify(int heapArray[], int i, int heap_size);
    void heapSort(int heapArray[], int heap_size);
private:
    int size;
    int* maxHeap;
    int index;
    int i;
};
Heaparr::Heaparr() {
    maxHeap = nullptr;
    size = 0;
}
void Heaparr::insert(int da) {
    size++;
    int* tmp = new int[size];
    for (int i = 0; i < size - 1; i++) {
        tmp[i] = maxHeap[i];
    }
    tmp[size - 1] = da;
    delete[] maxHeap;
    maxHeap = tmp;
}
void Heaparr::heapSort(int heapArray[], int heap_size) {
    size = heap_size;
    int n = size;
    Build_Max_Heap(heapArray, heap_size);
    for (int i = n - 1; i >= 1; i--) {
        std::swap(heapArray[0], heapArray[i]);
        heap_size = heap_size - 1;
        Max_Heapify(heapArray, 0, heap_size);
    }
}
void Heaparr::Build_Max_Heap(int heapArray[], int heap_size) {
    int n = size;
    for (int i = floor((n - 1) / 2); i >= 0; i--) {
        Max_Heapify(heapArray, i, heap_size);
    }
    return;
}
void Heaparr::Max_Heapify(int heapArray[], int i, int heap_size) {
    // int n = size;
    int largest = 0;
    int l = getLeft(i);
    int r = getRight(i);
    if ((l < heap_size) && (heapArray[l] < heapArray[i])) {
        largest = l;
    } else {
        largest = i;
    }
    if ((r < heap_size) && (heapArray[r] < heapArray[largest])) {
        largest = r;
    }
    if (largest != i) {
        std::swap(heapArray[i], heapArray[largest]);
        Max_Heapify(heapArray, largest, heap_size);
    }
    return;
}
int main(int argc, char* argv[]) {
    int hArray[8] = {5, 99, 32, 4, 1, 12, 15, 8};
    Heaparr t;
    t.heapSort(hArray, sizeof(hArray)/sizeof(hArray[0]));
    for (auto v : hArray) {
        std::cout << v << ", ";
    }
    std::cout << std::endl;
    return 0;
}

输出:99, 32, 15, 12, 8, 5, 4, 1,

如果您愿意考虑其他实现,那么这里有一个:

#define MIN_TYPE  0
#define MAX_TYPE ~0
template<int TYPE,typename ITEM>
class Heap
{
public:
    Heap(int iMaxNumOfItems);
    virtual ~Heap();
public:
    bool AddItem(ITEM*  pItem);
    bool GetBest(ITEM** pItem);
protected:
    int  BestOfTwo(int i,int j);
    void SwapItems(int i,int j);
protected:
    ITEM** m_aItems;
    int    m_iMaxNumOfItems;
    int    m_iCurrNumOfItems;
};
template<int TYPE,typename ITEM>
Heap<TYPE,ITEM>::Heap(int iMaxNumOfItems)
{
    m_iCurrNumOfItems = 0;
    m_iMaxNumOfItems = iMaxNumOfItems;
    m_aItems = new ITEM*[m_iMaxNumOfItems];
    if (!m_aItems)
        throw "Insufficient Memory";
}
template<int TYPE,typename ITEM>
Heap<TYPE,ITEM>::~Heap()
{
    delete[] m_aItems;
}
template<int TYPE,typename ITEM>
bool Heap<TYPE,ITEM>::AddItem(ITEM* pItem)
{
    if (m_iCurrNumOfItems == m_iMaxNumOfItems)
        return false;
    m_aItems[m_iCurrNumOfItems] = pItem;
    for (int i=m_iCurrNumOfItems,j=(i+1)/2-1; j>=0; i=j,j=(i+1)/2-1)
    {
        if (BestOfTwo(i,j) == i)
            SwapItems(i,j);
        else
            break;
    }
    m_iCurrNumOfItems++;
    return true;
}
template<int TYPE,typename ITEM>
bool Heap<TYPE,ITEM>::GetBest(ITEM** pItem)
{
    if (m_iCurrNumOfItems == 0)
        return false;
    m_iCurrNumOfItems--;
    *pItem = m_aItems[0];
    m_aItems[0] = m_aItems[m_iCurrNumOfItems];
    for (int i=0,j=(i+1)*2-1; j<m_iCurrNumOfItems; i=j,j=(i+1)*2-1)
    {
        if (j+1 < m_iCurrNumOfItems)
            j = BestOfTwo(j,j+1);
        if (BestOfTwo(i,j) == j)
            SwapItems(i,j);
        else
            break;
    }
    return true;
}
template<int TYPE,typename ITEM>
int Heap<TYPE,ITEM>::BestOfTwo(int i,int j)
{
    switch (TYPE)
    {
        case MIN_TYPE: return *m_aItems[i]<*m_aItems[j]? i:j;
        case MAX_TYPE: return *m_aItems[i]>*m_aItems[j]? i:j;
    }
    throw "Illegal Type";
}
template<int TYPE,typename ITEM>
void Heap<TYPE,ITEM>::SwapItems(int i,int j)
{
    ITEM* pItem = m_aItems[i];
    m_aItems[i] = m_aItems[j];
    m_aItems[j] = pItem;
}

下面是一个用法示例:

typedef int ITEM;
#define SIZE 1000
#define RANGE 100
void test()
{
    ITEM* pItem;
    ITEM aArray[SIZE];
    Heap<MIN_TYPE,ITEM> cHeap(SIZE);
    srand((unsigned int)time(NULL));
    for (int i=0; i<SIZE; i++)
    {
        aArray[i] = rand()%RANGE;
        cHeap.AddItem(aArray+i);
    }
    for (int i=0; i<SIZE; i++)
    {
        cHeap.GetBest(&pItem);
        printf("%dn",*pItem);
    }
}

描述:

  • 该类最多存储T类型的N

  • 它允许添加一个项目或提取最佳项目

  • 支持的操作在O(log(n))完成,其中n为当前项数

备注:

  • T在声明时确定,N在初始化时确定

  • "最佳"的含义,无论是最小还是最大,在声明时确定

  • 为了支持Heap<MIN,T>Heap<MAX,T>,以下选项之一必须是可行的:

    1. bool operator<(T,T)bool operator>(T,T)

    2. bool T::operator<(T)bool T::operator>(T)

    3. T::operator P(),其中P是一种类型,对于它,上述选项之一是可行的