数据结构—堆

来源:互联网 发布:航信开票软件 编辑:程序博客网 时间:2024/05/22 06:20


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

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

#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.通过我们的比较器模板化,可将堆定义为大堆或者小堆,默认参数为大堆。

原创粉丝点击