数据结构—堆


堆数据结构是一种数组对象,它可以被视为一科完全二叉树结构。它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆)。它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等。

最小堆:任一结点的关键码均小于等于它的左右孩子的关键码,位于堆顶结点的关键码最小。
最大堆:任一结点的关键码均大于等于它的左右孩子的关键码,位于堆顶结点的关键码最大。
这里写图片描述

#pragma once
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;

template <class T>                                //比较器模板
struct Greater
{
    bool operator ()(const T& a, const T& b)
    {
        return a > b;
    }
};

template <class T>                               //比较器模板
struct Less
{
    bool operator ()(const T& a,const T& b)
    {
        return a < b;
    }
};

template <class T,class Comparator = Less<T>>
class Heap
{
public:

    Heap()                                       //构造函数(无节点)                
    {}

    Heap(T* a, size_t size)                      //构造函数(创造堆)
    {
        Creatheap(a, size);
    }

    void Creatheap(const T* a, int size);         //创建堆

    void Adjustup(size_t child);                  //向上调节

    void Adjustdown(size_t root);                 //向下调节

    void Push(const T& a);                        //往对中压入一个值

    void Pop();                                   //将堆顶端节点去除

    T& Top();                                     //显示堆顶端节点

    bool Empty();                                 //检测堆是否为空

    void Display();                               //打印堆中的值

private:
    vector<T> _arr;                               //STL vector创建一个数组
};

template<class T, class Comparator>
inline void Heap<T,Comparator>::Creatheap(const T* a,int size)
{
    _arr.reserve(size);
    for (int idx = 0; idx < size; idx++)
    {
        _arr.push_back(a[idx]);
    }
    for (int i = (_arr.size() - 2 )/ 2; i>-1;i--)
    {
        Adjustdown(i);
    }
}

template<class T,class Comparator>
inline void Heap<T, Comparator>::Adjustup(size_t child)
{
    int parent = (child - 1) / 2;
    while (parent >= 0)
    {
        if (Comparator()(_arr[child], _arr[parent]))
            swap(_arr[parent], _arr[child]);
        else
            break;
    }
}

template<class T,class Comparator>
inline void Heap<T, Comparator>::Adjustdown(size_t root)
{
    size_t parent = root;
    size_t child = parent * 2 + 1;
    while (child < _arr.size())
    {
        if (child + 1 < _arr.size() && Comparator()(_arr[child + 1], _arr[child]))
            child++;
        if (Comparator()(_arr[child], _arr[parent]))
        {
            swap(_arr[child], _arr[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
            break;
    }
}

template<class T, class Comparator>
inline void Heap<T, Comparator>::Push(const T& a)
{
    _arr.Push_back(a);
    Adjustup(_arr.size() - 1);
}

template<class T,class Comparator>
inline void Heap<T, Comparator>::Pop()
{
    assert(!Heap.Empty())
    swap(_arr[0], _arr[_arr.size() - 2]);
    _arr.Pop_back;
    Adjustdown(0);
}

template<class T,class Comparator>
inline T& Heap<T, Comparator>::Top()
{
    assert(!Heap.Empty())
    return _arr[0];
}

template<class T,class Comparator>
inline bool Heap<T, Comparator>::Empty()
{
    return _arr.empty();
}

template<class T,class Comparator>
inline void Heap<T, Comparator>::Display()
{
    for (size_t idx = 0; idx < _arr.size(); idx++)
    {
        cout << _arr[idx] << " ";
    }
}

这里写图片描述
这里写图片描述
这里写图片描述

1.在写堆的构造函数时,需要注意的是,创建一个空堆Heap()和创建一个有参数的Heap(T* a, size_t size)。
2.堆的创建函数void Creatheap(const T* a,int size)需要对容器vector实例化出来的_arr数组进行容量改变,满足放入数组大小,然后调用 _arr里的方法函数push _back()使数组放入容器,然后调用向下调整使其满足堆的条件。从最后一个叶子节点开始调整,一直调整到顶端节点。
3.向上调整中void Adjustup(size_t child)中,我们要得到孩子节点的形参,用孩子节点(child-1)/2得到他的双亲节点,进行比较,满足条件则交换,当双亲节点<0时,调整完毕。
4.向下调整void Adjustdown(size_t root)中,得到的是双亲节点,然后通过双亲节点得到他的左孩子节点,然后判断右孩子节点是否存在,如果存在找两个孩子中的最大值,然后用最大值与双亲节点进行比较,满足条件则进行交换。
5.void Pop()和T& Top()都需要先assert堆是否为空,当为空不能调用。
6.通过我们的比较器模板化,可将堆定义为大堆或者小堆,默认参数为大堆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值