如何实现最大堆
How to implement a max 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;
}
我做了一些固定的代码(我尽量不改变太多的原始代码):
-
getLeft
,getRight
和getParent
公式错误(例如:当i == 0
子节点必须为1和2,而您的代码为0和1)。返回类型也错误,应该是int
(数组索引)。 - 您是否在所有方法中接收
int[]
,除了insert
和member variable
中的double[]
,将所有更改为int[]
,如果您需要将所有更改回双 - 在数组中使用
std::swap
交换值 - 增加数组的长度到heapSort(在方法内部这个信息丢失,需要通过参数传递)。
指出:
- 我不知道你在哪里使用成员变量
maxHeap
,因为除了getMax
和insert
之外的所有方法都使用参数传递的数组,而不是成员变量(也许你应该在构造函数或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>
,以下选项之一必须是可行的:bool operator<(T,T)
和bool operator>(T,T)
bool T::operator<(T)
和bool T::operator>(T)
T::operator P()
,其中P
是一种类型,对于它,上述选项之一是可行的
相关文章:
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 如何实现内部实现依赖于模板参数的类
- 我的 PRNG 实现与我尝试复制的实现有何不同?