在删除 c ++ 时维护最小堆
Posted
技术标签:
【中文标题】在删除 c ++ 时维护最小堆【英文标题】:Maintaining a Min heap on deletion c++ 【发布时间】:2017-08-24 02:58:18 【问题描述】:测试用例:
8,7,5,2,3,6,9(不是最小堆)(这是 buildHeap 函数的元素 A*)
2,3,5,7,8,6,9(调用构建堆后的最小堆)
3,5,6,7,8,9(在调用 deleteMin 之后)这是不正确的
应该是这个3,7,5,9,8,6
我似乎无法找到 deleteMin 的问题,我知道我的 heapify 正在工作,但我可能没有看到任何东西。
Element Heap::deleteMin(Heap& heap)
Element deleted = heap.H[0];
heap.H[0] = heap.H[heap.size-1];
heap.size--;
cout<<deleted.getKey()<<" has been deleted from heap"<<endl;
for(int i=heap.capacity/2-1;i>=0;--i)
heapify(heap,i);
return deleted;
void Heap::heapify(Heap& heap,int index)
int smallest = 0;
int left = 2*index;
int right = 2*index+1;
if(left < heap.size && heap.H[left].getKey() < heap.H[index].getKey())
smallest=left;
else
smallest=index;
if(right < heap.size && heap.H[right].getKey() < heap.H[smallest].getKey())
smallest=right;
if(smallest != index)
int swapKey = heap.H[index].getKey();
heap.H[index].setKey(heap.H[smallest].getKey());
heap.H[smallest].setKey(swapKey);
heapify(heap,smallest);
void Heap::buildHeap(Heap& heap, Element* A)
for(int j=0;j<heap.capacity;++j)
heap.insert(heap,A[j]);
for(int i=heap.capacity/2-1;i>=0;--i)
heapify(heap,i);
【问题讨论】:
您是否尝试使用调试器单步执行您的代码? 我们不知道“heapify”应该做什么,所以除了“heapify 正在做它正在做的事情”之外我们不能说什么。但是,我会注意到您的语句“if(smallest != index)”,其中您将数组中的值与数组的索引进行比较,这看起来肯定不正确 - 例如,如果您将 100 添加到所有数组中的值(如 108,107、105 等),那么对于 7 个元素的数组,该条件将始终返回 false - 它看起来不正确。 @racraman:heapify
是实现堆时的常见操作。它在堆中筛选一个项目。它通常也称为siftDown
。如果您更仔细地检查heapify
,您会发现smallest
是数组的索引,而不是数组中的值。
【参考方案1】:
第一个问题是您对子索引的计算是错误的。如果你使用H[0]
作为堆的根,那么
left = (2*index)+1
right = (2*index)+2
您的计算假设根位于H[1]
。
另一个问题是你在 deleteMin
函数中做了太多工作:
Element Heap::deleteMin(Heap& heap)
Element deleted = heap.H[0];
heap.H[0] = heap.H[heap.size-1];
heap.size--;
cout<<deleted.getKey()<<" has been deleted from heap"<<endl;
for(int i=heap.capacity/2-1;i>=0;--i)
heapify(heap,i);
return deleted;
删除最小项并将最后一项放入堆中的根后,您只需调用heapify(heap, 0);
在该循环中没有理由重新构建整个堆。
所以你的函数变成了:
Element Heap::deleteMin(Heap& heap)
Element deleted = heap.H[0];
heap.H[0] = heap.H[heap.size-1];
heap.size--;
cout<<deleted.getKey()<<" has been deleted from heap"<<endl;
heapify(heap, 0);
return deleted;
您的buildHeap
方法同样做了太多工作。
您可能对堆的复习感兴趣。我在http://blog.mischel.com/2013/09/29/a-better-way-to-do-it-the-heap/ 的博客文章用非常简单的术语解释了它们的操作,我的simple heap of integers 显示了一个简单的实现。它使用 C# 而不是 C++,但代码非常相似。你应该可以毫无困难地理解它。
【讨论】:
以上是关于在删除 c ++ 时维护最小堆的主要内容,如果未能解决你的问题,请参考以下文章