如何实现最大堆

时间:2014-07-31 17:33:49

标签: c++ arrays heap

我有构建最大堆的代码,但它继续返回我给它的相同数组。我确定这是一个小错误,但我似乎无法弄明白。任何帮助表示赞赏。

可编辑的示例代码:

#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;
}

2 个答案:

答案 0 :(得分:1)

我对代码做了一些修改(我尽量不改变原代码):

  • getLeftgetRightgetParent公式错误(例如:当i == 0个孩子必须 1和2 并且使用您的代码时是 0和1 。返回类型也是错误的,应该是int(数组索引)。
  • 您是否在所有方法中收到int[]insertmember variable double[]以外的int[],如果您需要更改,则全部更改为std::swap返回所有 double
  • 使用maxHeap表示数组中的交换值。
  • 将数组的长度添加到heapSort(在方法内部,此信息丢失,需要通过参数传递)。

注意:

  • 我看不到你使用成员变量getMax的位置,因为除了insertheapSort之外的所有方法都使用通过参数传递的数组而不是成员变量(也许你应该初始化构造函数或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,

输出: {{1}}

使用C ++ 11在GCC 4.9.0中测试

答案 1 :(得分:0)

如果您愿意考虑替代实施,那么这里有一个:

#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("%d\n",*pItem);
    }
}

说明

  • 此类最多可存储N类型的T

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

  • 支持的操作在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是一种类型,上述选项之一是可行的