我正在尝试使用这个堆。我插入一些随机数,然后删除它们以确保我的堆工作。问题是当我删除它们时,我得到堆中不应存在的重复数字。几乎我会插入以下数字并返回:5 2 10 10
由于某种原因。
我的主要看起来像这样:
#include <iostream>
#include <fstream>
using namespace std;
#include "heap.h"
int main(void)
{
Heap<int> inlist(4);
inlist.insert(5);
inlist.insert(2);
inlist.insert(3);
inlist.insert(10);
int test;
while(inlist.remove(test))
cout << test << endl;
}
我的Heap看起来像这样:
#ifndef HEAP_H
#define HEAP_H
template<typename TYPE>
class Heap
{
private:
TYPE* heapData;
int currSize;
int capacity;
void _siftUp(int);
void _siftDown(int);
int _leftChildOf(int) const;
int _parentOf(int) const;
public:
Heap(int c = 100);
~Heap();
bool viewMax(TYPE&) const;
int getCapacity() const;
int getCurrSize() const;
bool insert(const TYPE&);
bool remove(TYPE&);
};
template<typename TYPE>
Heap<TYPE>::Heap(int c = 100)
{
capacity = 100;
currSize = 0;
heapData = new TYPE[capacity];
}
template<typename TYPE>
Heap<TYPE>::~Heap()
{
delete[] heapData;
currSize = 0;
capacity = 0;
}
template<typename TYPE>
bool Heap<TYPE>::insert(const TYPE& dataIn)
{
bool success = false;
if(currSize < capacity)
{
heapData[currSize] = dataIn;
_siftUp(currSize);
currSize++;
success = true;
}
return success;
}
template<typename TYPE>
void Heap<TYPE>::_siftUp(int child)
{
TYPE temp;
int parent;
if(child > 0)
{
parent = _parentOf(child);
if(heapData[child] > heapData[parent])
{
temp = heapData[parent];
heapData[parent] = heapData[child];
heapData[child] = temp;
_siftUp(child);
}
}
}
template<typename TYPE>
bool Heap<TYPE>::remove(TYPE& dataOut)
{
bool success = false;
if(currSize > 0)
{
dataOut = heapData[0];
currSize--;
heapData[0] = heapData[currSize];
_siftDown(0);
success = true;
}
return success;
}
template<typename TYPE>
void Heap<TYPE>::_siftDown(int parent)
{
TYPE temp;
int child = _leftChildOf(parent);
if(child < currSize)
{
if((child + 1 < currSize) && (heapData[child] < heapData[child + 1]))
child++;
if(child)
{
temp = heapData[child];
heapData[child] = heapData[child + 1];
heapData[child + 1] = temp;
_siftDown(child);
}
}
}
template<typename TYPE>
int Heap<TYPE>::_leftChildOf(int p) const
{
return(2 * p + 1);
}
template<typename TYPE>
int Heap<TYPE>::_parentOf(int c) const
{
return((c - 1) / 2);
}
//**************************************************************************
template<typename TYPE>
int Heap<TYPE>::getCapacity() const
{
return capacity;
}
template<typename TYPE>
int Heap<TYPE>::getCurrSize() const
{
return currSize;
}
template<typename TYPE>
bool Heap<TYPE>::viewMax(TYPE& max) const
{
return false;
}
#endif
我很确定问题不在我插入堆时,而是当我将其移除时。
编辑我稍微更改了_siftDown - 现在数字显示5 10 3 2
if(child)
{
temp = heapData[child];
heapData[child] = heapData[parent];
heapData[parent] = temp;
_siftDown(child);
}
答案 0 :(得分:2)
您的_siftDown
已损坏,
template<typename TYPE>
void Heap<TYPE>::_siftDown(int parent)
{
TYPE temp;
int child = _leftChildOf(parent);
if(child < currSize)
{
if((child + 1 < currSize) && (heapData[child] < heapData[child + 1]))
child++;
if(child)
这意味着检查什么? child
此时2*parent + 1
或2*parent + 2
没有溢出,因为parent
应始终为>= 0
,这始终是正的〜&gt;条件得到满足。
您需要检查是否要交换heapData[parent]
和heapData[child]
,以便条件应为if (heapData[parent] < heapData[child])
。
{
temp = heapData[child];
heapData[child] = heapData[child + 1];
heapData[child + 1] = temp;
您正在交换索引child
和child+1
的元素,这是错误的。您应该在这里交换heapData[child]
和heapData[parent]
。
_siftDown(child);
}
}
}
_siftUp
,
template<typename TYPE>
void Heap<TYPE>::_siftUp(int child)
{
TYPE temp;
int parent;
if(child > 0)
{
parent = _parentOf(child);
if(heapData[child] > heapData[parent])
{
temp = heapData[parent];
heapData[parent] = heapData[child];
heapData[child] = temp;
_siftUp(child);
}
}
}
递归调用应为_siftUp(parent)
,否则您永远不会将任何项目筛选到多个级别。
答案 1 :(得分:1)
你的删除方法很好,而你的_siftDown有问题。 你和你的左孩子一起倒下并不总是正确的。
void Heap<TYPE>::_siftDown(int parent)
{
TYPE temp;
int left= _leftChildOf(parent);
int right= _rightChildOf(parent);
int max= parent;
if(left< currSize && heapData[left] > heapData[max])
{
max= left;
}
if(right< currSize && heapData[right] > heapData[max])
{
max= right;
}
if( max!=parent ) //need to sift down
{
temp = heapData[max];
heapData[max] = heapData[parent];
heapData[parent] = temp;
_siftDown(max);
}
}
}
答案 2 :(得分:0)
您可以使用以下函数而不是实现自己的堆:
std::make_heap
std::push_heap
std::pop_heap
您可以在算法标题中找到它们
答案 3 :(得分:0)
heapData[0] = heapData[currSize];
在这里你不应该使用heapData[currSize]
,否则你将堆的最后一个元素复制到顶部。
例如,从堆5
中删除currSize
后3
并执行
heapData[0] = heapData[3];
将在10
创建heapData[0]
的副本。
答案 4 :(得分:-1)
无需仔细查看代码 你意识到测试从未被初始化?
int test; //initialization should happen here
while(inlist.remove(test))
cout << test << endl;
我也不明白Heap :: remove(dataOut)参数的用途是什么。它与Heap :: remove(void)不同吗?