C++11标准模板(STL)- 算法 – 堆操作(std::push_heap)

  • Post author:
  • Post category:其他


定义于头文件 <algorithm>

算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。注意范围定义为

[first, last)

,其中

last

指代要查询或修改的最后元素的

后一个

元素。

数据结构的堆

物理结构是数组



逻辑结构是完全二叉树

将一个元素加入到一个最大堆

std::push_heap

template< class RandomIt >

void push_heap( RandomIt first, RandomIt last );

(1) (C++20 前)

template< class RandomIt >

constexpr void push_heap( RandomIt first, RandomIt last );

(C++20 起)
template< class RandomIt, class Compare >

void push_heap( RandomIt first, RandomIt last,

Compare comp );

(2) (C++20 前)
template< class RandomIt, class Compare >

constexpr void push_heap( RandomIt first, RandomIt last,

Compare comp );

(C++20 起)

插入位于位置

last-1

的元素到范围

[first, last-1)

所定义的

最大堆

中。函数的第一版本用 operator< 比较元素,第二版本用给定的比较函数

comp

参数

first, last 定义要修改的堆的元素范围
comp 比较函数对象(即满足

比较

(Compare) 要求的对象),若首个参数

小于

第二个,则返回 ​true 。

比较函数的签名应等价于如下:

bool cmp(const Type1 &a, const Type2 &b);

虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型

Type1



Type2

的值,无关乎值类别(从而不允许 Type1 & ,亦不允许 Type1 ,除非

Type1

的移动等价于复制 (C++11 起))。

类型 Type1 与 Type2 必须使得 RandomIt 类型的对象能在解引用后隐式转换到这两个类型。 ​

类型要求


RandomIt

必须满足

遗留随机访问迭代器

(LegacyRandomAccessIterator) 的要求。
– 解引用

RandomIt

结果的类型必须满足

可移动赋值

(MoveAssignable) 和

可移动构造

(MoveConstructible) 的要求。

返回值

(无)

复杂度

至多

log(N)

次比较,其中 N=std::distance(first, last) 。

注意


最大堆

是拥有下列属性的元素范围

[f,l)



  • N = l - f

    ,对于所有

    0 < i < N



    f[floor(

    i-1
    2


    )]

    不小于

    f[i]

  • 可用 std::push_heap() 添加新元素
  • 可用 std::pop_heap() 移除首元素

调用示例

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <iterator>
#include <time.h>

using namespace std;

struct Cell
{
    int x;
    int y;

    Cell &operator +=(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    bool operator <(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }
};

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}

int main()
{
    srand((unsigned)time(NULL));;

    std::cout.setf(std::ios_base::boolalpha);

    auto func1 = []()
    {
        int n = std::rand() % 10 + 100;
        Cell cell{n, n};
        return cell;
    };

    // 初始化cells1
    vector<Cell> cells1(5);
    std::generate(cells1.begin(), cells1.end(), func1);

    // 生成堆
    std::make_heap(cells1.begin(), cells1.end());

    // 打印cells1
    std::cout << "cells 1 :         ";
    std::copy(cells1.begin(), cells1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_heap:          " << std::is_heap(cells1.begin(), cells1.end()) << std::endl;
    std::cout << std::endl;

    cells1.push_back(func1());
    std::cout << "before push_heap: ";
    std::copy(cells1.begin(), cells1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_heap:          " << std::is_heap(cells1.begin(), cells1.end()) << std::endl;
    std::cout << std::endl;

    //插入位于位置 last-1 的元素到范围 [first, last-1) 所定义的最大堆中。
    std::push_heap(cells1.begin(), cells1.end());

    // 打印cells1
    std::cout << "after push_heap:  ";
    std::copy(cells1.begin(), cells1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_heap:          " << std::is_heap(cells1.begin(), cells1.end()) << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;


    auto is_sortf = [](const Cell & a, const Cell & b)
    {
        if (a.x == b.x)
        {
            return a.y > b.y;
        }
        return a.x > b.x;
    };

    // 初始化cells2
    vector<Cell> cells2(5);
    std::generate(cells2.begin(), cells2.end(), func1);

    // 生成堆
    std::make_heap(cells2.begin(), cells2.end(), is_sortf);

    // 打印cells1
    std::cout << "cells2:           ";
    std::copy(cells2.begin(), cells2.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_heap:          " << std::is_heap(cells2.begin(), cells2.end(), is_sortf) << std::endl;
    std::cout << std::endl;

    cells2.push_back(func1());

    std::cout << "before push_heap: ";
    std::copy(cells2.begin(), cells2.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_heap:          " << std::is_heap(cells2.begin(), cells2.end()) << std::endl;
    std::cout << std::endl;

    //插入位于位置 last-1 的元素到范围 [first, last-1) 所定义的最大堆中。
    std::push_heap(cells2.begin(), cells2.end(), is_sortf);

    // 打印cells2
    std::cout << "after push_heap:  ";
    std::copy(cells2.begin(), cells2.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_heap:          " << std::is_heap(cells2.begin(), cells2.end(), is_sortf) << std::endl;

    return 0;
}

输出



版权声明:本文为qq_40788199原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。