【问题标题】:Maintaining a Min heap on deletion c++在删除 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 是数组的索引,而不是数组中的值。

标签: c++ heap heapsort binary-heap


【解决方案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++,但代码非常相似。你应该可以毫无困难地理解它。

【讨论】:

    猜你喜欢
    • 2011-12-02
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 2022-01-22
    • 2023-03-13
    • 2019-04-09
    • 2018-05-19
    相关资源
    最近更新 更多