为啥 is_heap() 不验证我创建的堆,尽管它在概念上是有效的

Posted

技术标签:

【中文标题】为啥 is_heap() 不验证我创建的堆,尽管它在概念上是有效的【英文标题】:Why is_heap() not validating the heap created by me though it is valid conceptually为什么 is_heap() 不验证我创建的堆,尽管它在概念上是有效的 【发布时间】:2017-07-31 15:52:14 【问题描述】:

我用 C++ 编写了一个堆实现,今天晚些时候我才知道,C++11 中有内置函数可以使任何基于范围的容器成为堆。

所以出于好奇,我使用自己的实现将向量放入堆中,并使用了函数make_heap(),然后对它们都运行了is_heap()

使用make_heap() 制作的那个验证为true,但我没有,即使它在技术上是有效的。

源码及截图如下

头文件

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <cmath>
using namespace std;

主堆函数

vector<int> heapify(vector<int> nums, string const & type) 
    int n = nums.size();
    for (int i = n - 1; i >= 0; i--) 
        int parent = floor((i-1)/2);

        if (parent >= 0) 
            if (type == "min") 
                if (nums[i] < nums[parent]) 
                    swap(nums[i], nums[parent]);
                
             else 
                if (nums[i] > nums[parent]) 
                    swap(nums[i], nums[parent]);
                
            
        
    
    return nums;

构建堆的函数

vector<int> buildHeap(vector<int> const & nums, string const & type) 
    vector<int> heap;
    int n = nums.size();
    for (int i = 0; i < n; i++) 
        heap.push_back(nums[i]);
        if (!heap.empty()) 
            heap = heapify(heap, type);
        
    
    return heap;

删除最顶部的元素

int getTop(vector<int> & nums, string const & type) 
    int n = nums.size();
    if (n < 0) 
        throw string("Size of array is less than 0");
     else 
        int minElem = nums[0];
        swap(nums[0], nums[n-1]);
        nums.pop_back();
        nums = heapify(nums, type);
        return minElem;
    

主要功能

int main()

    vector<int> nums = 45, 56, 78, 89, 21, 38, 6, 67, 112, 45, 3, 1;
    vector<int> heap = buildHeap(nums, "min");
    for (int num : heap) 
        cout << num << " ";
    
    cout << "\n";

    cout << std::is_heap(nums.begin(), nums.end(), greater<int>()) << "\n";
    make_heap(nums.begin(), nums.end(), greater<int>());
    for (int num : nums) 
        cout << num << " ";
    
    cout << "\n";
    cout << std::is_heap(nums.begin(), nums.end(), greater<int>()) << "\n";
    return 0;

控制台输出和https://www.cs.usfca.edu/~galles/visualization/Heap.html 验证的屏幕截图

【问题讨论】:

你的谓词被颠倒了 在哪里?你能指出我错的源代码或逻辑吗? 请重构您发布的代码,以便我可以将其剪切/粘贴到我的 IDE 中。然后我会更新它来告诉你在哪里 我绝对不会安装 gcc 来测试你的代码。 @deadpoolAlready -- 帮助你的人可能没有 GCC。再次,包括正确的标题。关于为什么不应该使用“bits/stdc++.h”有一个重复的问题。了解实际标题有什么问题? 【参考方案1】:

您不在堆上运行第一个 is_heap,而是在原始向量上运行它。那显然不是堆。

这一行没有检查你的堆:

cout << std::is_heap(nums.begin(), nums.end(), greater<int>()) << "\n";

你的堆变量叫做heap:

cout << std::is_heap(heap.begin(), heap.end(), greater<int>()) << "\n";

【讨论】:

我想使用is_heap()检查我使用我的代码实际开发的堆是否有效。 是的,现在明白了。我犯了一个可怕的错误:D【参考方案2】:

您的实现将堆作为原始序列的副本。所以你需要验证副本(heap),而不是原始序列(nums)。

    cout << std::is_heap(heap.begin(), heap.end(), greater<int>()) << "\n";

你的序列一个堆,here's proof:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()

    vector<int> vec = 1, 6, 3, 67, 45, 21, 38, 89, 112, 56, 45, 78;
    std::cout << is_heap(vec.begin(), vec.end(), greater<int>());

输出:

1

【讨论】:

我错过了。我在堆上检查了它,现在它工作得很好:/对不起,我的错。感谢您指出。

以上是关于为啥 is_heap() 不验证我创建的堆,尽管它在概念上是有效的的主要内容,如果未能解决你的问题,请参考以下文章

为啥路由器链接不起作用,尽管我使用与 href 相同的组件链接并且它可以工作?

尽管身份验证完成,为啥 SpringBoot Security 不向 REST 客户端返回任何响应

为啥在由数组实现的堆中,索引 0 未被使用?

为啥 ngfor 指令不起作用,尽管我在 Typescript 类中创建了正确的对象

为啥这种带有动态输入值的表单验证不起作用?

为啥我总是得到一个不允许通配符 * 的 cors 错误,尽管我在服务器上指定了一个来源?