堆的简单实现

堆数据结构是一种数组对象,可被视为一颗完全二叉树
堆结构的二叉树存储
最大堆:父>子
最小堆:父<子
如下图,先建立一个大堆
这里写图片描述
下面用代码模拟实现一个大堆(插入 ,头删)

#include <iostream>
#include <vector>
#include <assert.h>

using namespace std;

template <class T>
class Heap
{
public:
    Heap()
    {}
    Heap(const T* a, size_t n)
    {
        _a.reserve(n);//开辟n个空间
        for (size_t i = 0; i < n; i++)
        {
            _a.push_back(a[i]);//插入数据
        }
        int parent = (n - 1) / 2;
        for (parent; parent>=0; parent--)
        {
            adjustdown(parent);//向下调整 建大堆
        }
    }
     void show()
    {
        if (_a.size())
        {
            for (size_t i = 0; i <_a.size(); i++)
            {
                printf("%3d ",_a[i]);
            }printf("\n");
        }
    }
     void push(const T& x)
     {
         _a.push_back(x);//尾插
         adjustup(_a.size()-1);//向上调整

     }
     void pop()
     {
         assert(_a.size());
         swap(_a[0], _a[_a.size() - 1]);
         _a.pop_back();//尾删,然后向下调整
         adjustdown(0);
     }

protected:
    vector<T> _a;
    void adjustdown(int parent)//向下调整
    {
        int child = parent * 2 + 1;
        while (child<_a.size())
        {
            //当右孩子存在,且大于左孩子时
            if (child + 1 < _a.size() && _a[child + 1] > _a[child])
                ++child;


            if (_a[child] > _a[parent])//当孩子大于父亲时,交换
            {
                swap(_a[child], _a[parent]);
                parent = child;
                child = parent * 2 + 1;

            }
            else
            {
                break;
            }
        }
    }
    void adjustup(int child)//向上调整
    {
        int parent = (child - 1) / 2;
        while (child > 0)
        {
            if (_a[child] > _a[parent])//当孩子大于父亲时,交换
            {
                swap(_a[child],_a[parent]);
                child = parent;
                parent = (child - 1) / 2;
            }
            else break;
        }
    }

};


void main()
{
    int a[] = { 12,13,14,15,16,17,20,21,25};
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%3d ", a[i]);
    }
    printf("\n");


    Heap<int>hp(a, sizeof(a) / sizeof(a[0]));
    hp.show();
    hp.push(23);  printf("hp.push(23)\n");
    hp.show();
    hp.pop();   printf("hp.pop();\n");
    hp.show();

    system("pause");
}

结果如下
这里写图片描述
如上就是堆的简单实现,再进一步可以将建大小堆关键判断语句用仿函数代替

#pragma once
#include <iostream>
#include <vector>
#include <assert.h>

using namespace std;
template<class T>
struct Greater//建大堆
{
    bool operator()(const T& x1, const T& x2)
    {
        return x1 > x2;
    }
};
template<class T>
struct Less//建小堆
{
    bool operator()(const T& x1, const T& x2)
    {
        return x1 < x2;
    }
};

template <class T,class Compare>
class Heap
{
public:
    Heap()
    {}
    Heap(const T* a, size_t n)
    {
        _a.reserve(n);//开辟n个空间
        for (size_t i = 0; i < n; i++)
        {
            _a.push_back(a[i]);//插入数据
        }
        int parent = (n - 1) / 2;
        for (parent; parent >= 0; parent--)
        {
            adjustdown(parent);//向下调整 建大堆
        }
    }
    void show()
    {
        if (_a.size())
        {
            for (size_t i = 0; i <_a.size(); i++)
            {
                printf("%3d ", _a[i]);
            }printf("\n");
        }
    }
    void push(const T& x)//尾插
    {
        _a.push_back(x);//尾插
        adjustup(_a.size() - 1);//向上调整

    }
    void pop()//删除堆顶元素
    {
        assert(_a.size());
        swap(_a[0], _a[_a.size() - 1]);
        _a.pop_back();//尾删,然后向下调整
        adjustdown(0);
    }
    size_t Size()
    {
        return _a.size();
    }
    const T& Top()
    {
        return _a[0];
    }

protected:
    vector<T> _a;


    void adjustdown(int parent)//向下调整
    {
        Compare com;//
        int child = parent * 2 + 1;
        while (child<_a.size())
        {
            //当右孩子存在,且大于/小于左孩子时
            if (child + 1 < _a.size() && com(_a[child +1] , _a[child]))//此处用仿函数替换
                ++child;


            if (com(_a[child] , _a[parent]))//当孩子大于/小于父亲时,交换
            {
                swap(_a[child], _a[parent]);
                parent = child;
                child = parent * 2 + 1;

            }
            else
            {
                break;
            }
        }
    }
    void adjustup(int child)//向上调整
    {
        Compare com;//
        int parent = (child - 1) / 2;
        while (child > 0)
        {
            //此处用仿函数替换
            if (com(_a[child] , _a[parent]))//当孩子大于/小于父亲时,交换
            {
                swap(_a[child], _a[parent]);
                child = parent;
                parent = (child - 1) / 2;
            }
            else break;
        }
    }

};


如上所示为用仿函数替换的堆,根据需要建大堆或小堆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值