堆的操作与应用1 -C++

堆1

堆的初始化

void heap_adjust(int x)
{
    while(x * 2 <= tot)
    {
        int j = x * 2;
        if(j + 1 <= tot && head[x * 2 + 1] > heap[x * 2])
        {
            j ++;
        }
        if(heap[j] > heappx)
        {
            swap(heap[x], heap[j]);
            x = j;
        }
        else
        {
            break;
        }
    }
}

void Adjust(int tot)
{
    for(int i = tot / 2; i >= 1; i --)
    {
        heap_adjust(i);
    }
}

合并果子

朴素版本

#include <iostream>
#include <cstdio>
#include <iomanip>

void upload_Lb(int k)
{
    while(k > 1)
    {
        if(h[k / 2] > h[k])
        {
            swap(h[k / 2], h[k]);
            k /= 2;
        }
        else
        {
            return ;
        }
    }
}

void down(int k)
{
    while(2 * k <= tot)
    {
        int j = 2 * k;
        if(j < tot && h[j + 1] < h[j])
        {
            j ++;
        }
        if(h[j] < h[k])
        {
            swap(h[j], h[k]);
            k = j;
        }
        else
        {
            return ;
        }
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d", h[i]);
        tot ++;
        up(tot);
    }
    for(int i = 1; i < n; i ++)
    {
        tmp = h[1];
        h[1] = h[tot--];
        down(1);
        tmp += h[1];
        h[1] = h[tot --];
        down(1);
        ans += tmp;
        h[++ tot] = tmp;
        up(tot);
    }
    printf("%d", ans);
    return 0;
}

STL - priority_queue <>

  • priority_queue <int, vector , greater > q; 升序队列,也称作小根堆
  • priority_queue <int, vector , less > q; 降序队列,也称作大根堆
  • priority_queue q; 默认为priority_queue <int, vector , greater > q; 升序队列
  • q.push(x); 插入一个元素
  • q.top(); 返回顶部元素
  • q.pop(); 删除顶部元素
  • q.size(); 返回 q q q的大小
  • q.empty(); 判断q是否为空
  • q.emplace(); 原地构造一个

代码:

template <class _Ty, class _Container = vector<_Ty>, class _Pr = less<typename _Container::value_type>>
class priority_queue {
public:
    using value_type      = typename _Container::value_type;
    using reference       = typename _Container::reference;
    using const_reference = typename _Container::const_reference;
    using size_type       = typename _Container::size_type;
    using container_type  = _Container;
    using value_compare   = _Pr;

    static_assert(is_same_v<_Ty, value_type>, "container adaptors require consistent types");

    priority_queue() = default;

    explicit priority_queue(const _Pr& _Pred) noexcept(
        is_nothrow_default_constructible_v<_Container>&& is_nothrow_copy_constructible_v<value_compare>) // strengthened
        : c(), comp(_Pred) {}

    priority_queue(const _Pr& _Pred, const _Container& _Cont) : c(_Cont), comp(_Pred) {
        _STD make_heap(c.begin(), c.end(), comp);
    }

    priority_queue(const _Pr& _Pred, _Container&& _Cont) : c(_STD move(_Cont)), comp(_Pred) {
        _STD make_heap(c.begin(), c.end(), comp);
    }

    template <class _InIt>
    priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, const _Container& _Cont) : c(_Cont), comp(_Pred) {
        c.insert(c.end(), _First, _Last);
        _STD make_heap(c.begin(), c.end(), comp);
    }

    template <class _InIt>
    priority_queue(_InIt _First, _InIt _Last) : c(_First, _Last), comp() {
        _STD make_heap(c.begin(), c.end(), comp);
    }

    template <class _InIt>
    priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred) : c(_First, _Last), comp(_Pred) {
        _STD make_heap(c.begin(), c.end(), comp);
    }

    template <class _InIt>
    priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, _Container&& _Cont) : c(_STD move(_Cont)), comp(_Pred) {
        c.insert(c.end(), _First, _Last);
        _STD make_heap(c.begin(), c.end(), comp);
    }

    template <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
    explicit priority_queue(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Container, const _Alloc&>&&
            is_nothrow_default_constructible_v<value_compare>) // strengthened
        : c(_Al), comp() {}

    template <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
    priority_queue(const _Pr& _Pred, const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Container, const _Alloc&>&&
            is_nothrow_copy_constructible_v<value_compare>) // strengthened
        : c(_Al), comp(_Pred) {}

    template <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
    priority_queue(const _Pr& _Pred, const _Container& _Cont, const _Alloc& _Al) : c(_Cont, _Al), comp(_Pred) {
        _STD make_heap(c.begin(), c.end(), comp);
    }

    template <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
    priority_queue(const _Pr& _Pred, _Container&& _Cont, const _Alloc& _Al) : c(_STD move(_Cont), _Al), comp(_Pred) {
        _STD make_heap(c.begin(), c.end(), comp);
    }

    template <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
    priority_queue(const priority_queue& _Right, const _Alloc& _Al) : c(_Right.c, _Al), comp(_Right.comp) {}

    template <class _Alloc, enable_if_t<uses_allocator_v<_Container, _Alloc>, int> = 0>
    priority_queue(priority_queue&& _Right, const _Alloc& _Al) noexcept(
        is_nothrow_constructible_v<_Container, _Container, const _Alloc&>&&
            is_nothrow_move_constructible_v<value_compare>) // strengthened
        : c(_STD move(_Right.c), _Al), comp(_STD move(_Right.comp)) {}

    _NODISCARD bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ {
        return c.empty();
    }

    _NODISCARD size_type size() const noexcept(noexcept(c.size())) /* strengthened */ {
        return c.size();
    }

    _NODISCARD const_reference top() const noexcept(noexcept(c.front())) /* strengthened */ {
        return c.front();
    }

    void push(const value_type& _Val) {
        c.push_back(_Val);
        _STD push_heap(c.begin(), c.end(), comp);
    }

    void push(value_type&& _Val) {
        c.push_back(_STD move(_Val));
        _STD push_heap(c.begin(), c.end(), comp);
    }

    template <class... _Valty>
    void emplace(_Valty&&... _Val) {
        c.emplace_back(_STD forward<_Valty>(_Val)...);
        _STD push_heap(c.begin(), c.end(), comp);
    }

    void pop() {
        _STD pop_heap(c.begin(), c.end(), comp);
        c.pop_back();
    }

    void swap(priority_queue& _Right) noexcept(
        _Is_nothrow_swappable<_Container>::value&& _Is_nothrow_swappable<_Pr>::value) {
        _Swap_adl(c, _Right.c);
        _Swap_adl(comp, _Right.comp);
    }

protected:
    _Container c{};
    _Pr comp{};
};

#if _HAS_CXX17
template <class _Pr, class _Container,
    enable_if_t<conjunction_v<negation<_Is_allocator<_Pr>>, negation<_Is_allocator<_Container>>>, int> = 0>
priority_queue(_Pr, _Container) -> priority_queue<typename _Container::value_type, _Container, _Pr>;

template <class _Iter, class _Pr = less<_Iter_value_t<_Iter>>, class _Container = vector<_Iter_value_t<_Iter>>,
    enable_if_t<conjunction_v<_Is_iterator<_Iter>, negation<_Is_allocator<_Pr>>, negation<_Is_allocator<_Container>>>,
        int> = 0>
priority_queue(_Iter, _Iter, _Pr = _Pr(), _Container = _Container())
    -> priority_queue<_Iter_value_t<_Iter>, _Container, _Pr>;

template <class _Pr, class _Container, class _Alloc,
    enable_if_t<conjunction_v<negation<_Is_allocator<_Pr>>, negation<_Is_allocator<_Container>>, _Is_allocator<_Alloc>,
                    uses_allocator<_Container, _Alloc>>,
        int> = 0>
priority_queue(_Pr, _Container, _Alloc) -> priority_queue<typename _Container::value_type, _Container, _Pr>;
#endif // _HAS_CXX17

template <class _Ty, class _Container, class _Pr,
    enable_if_t<_Is_swappable<_Container>::value && _Is_swappable<_Pr>::value, int> = 0>
void swap(priority_queue<_Ty, _Container, _Pr>& _Left, priority_queue<_Ty, _Container, _Pr>& _Right) noexcept(
    noexcept(_Left.swap(_Right))) {
    _Left.swap(_Right);
}

合并果字stl版

1

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;

int main()
{
    priority_queue <long long> q; // 可以是任意的类型
    long long ret = 0;
    int n;
    scanf("%d", &n);
    int x;
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d", &x);
        q.push(-x);
    }
    while(q.size() > 1)
    {
        long long a = -q.top();
        q.pop();
        long long b = -q.top();
        q.pop();
        ret += a + b;
        q.push(-a - b);
    }
    printf("%lld", ret);
    return 0;
}

2

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;

int n;
priority_queue <long long, vector <long long>, greater <long long> > q;

int main()
{
    long long x, y, sum = 0LL;
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
    {
        scanf("%lld", &x);
        q.push(x);
    }
    for(int i = 1; i < n; i ++)
    {
        x = q.top();
        q.pop();
        y = q.top();
        q.pop();
        sum += x + y;
        q.push(x + y);
    }
    printf("%lld\n", sum);
    return 0;
}

3

#include <cstdio>
#include <iostream>
#include <queue>

using namespace std;

struct node
{
    long long v;
    bool operator < (const struct node x) const
    {
        return v > x.v; // ^_^
    }
}
cur;

priority_queue <struct node> pq;

int main()
{
    int n;
    long long sum = 0;
    scanf("%d", &n);
    for(int i = 0; i < n; i ++)
    {
        scanf("%lld", &cur.v);
        pq.push(cur);
    }
    for(int i = 1; i <  n; i ++)
    {
        cur = pq.top();
        pq.pop();
        cur.v += pq.top().v;
        pq.pop();
        sum += cur.v;
        pq.push(cur);
    }
    printf("%lld\n", sum);
    return 0;
}

堆排序

  • 即利用堆的特性进行排序的一种排序方法。
  • 步骤:
      1. 建立初始大顶堆,即将整个序列调整为堆
      1. 输出根结点,将堆顶元素和最后元素交换,从堆中删除原来的堆顶元素
      1. 重新调整为大顶堆
      1. 重复第2、3步,直到所有的元素都被删除。

代码

#include <iostream>
#include <algorithm>
using namespace std;
 
void max_heapify(int arr[], int start, int end) 
{
    //建立父节点指标和子节点指标
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end)  //若子节点指标在范围内才做比较
    {    
        if (son + 1 <= end && arr[son] < arr[son + 1]) //先比较两个子节点大小,选择最大的
            son++;
        if (arr[dad] > arr[son]) //如果父节点大於子节点代表调整完毕,直接跳出函数
            return;
        else  //否则交换父子内容再继续子节点和孙节点比较
        {
            swap(arr[dad], arr[son]);
            dad = son;
            son = dad * 2 + 1;
        }
    }
}
 
void heap_sort(int arr[], int len) 
{
    //初始化,i从最後一个父节点开始调整
    for (int i = len / 2 - 1; i >= 0; i--)
        max_heapify(arr, i, len - 1);
    //先将第一个元素和已经排好的元素前一位做交换,再从新调整(刚调整的元素之前的元素),直到排序完毕
    for (int i = len - 1; i > 0; i--) 
    {
        swap(arr[0], arr[i]);
        max_heapify(arr, 0, i - 1);
    }
}
 
void main() 
{
    int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    heap_sort(arr, len);
    for (int i = 0; i < len; i++)
        cout << arr[i] << ' ';
    cout << endl;
    system("pause");
    return 0;
}

You got a dream, you gotta protect it. People can’t do something themselves, they wanna tell you you can’t do it. If you want something, go get it. Period.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值