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

时间:2017-07-31 15:52:15

标签: c++ algorithm c++11 heap

我用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

上的验证的屏幕截图

Output Console

Output verification

2 个答案:

答案 0 :(得分:3)

您没有在堆上运行第一个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";

答案 1 :(得分:1)

您的实现使堆成为原始序列的副本。因此,您需要验证副本(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