【数据结构】堆的实现(包括:默认成员函数,插元素push,删元素pop,访问根节点top,判空,大小)

来源:互联网 发布:阴线买入指标公式源码 编辑:程序博客网 时间:2024/06/03 03:36

在数据结构里,堆是一类很重要的结构。堆结构是一组数组对象,我们可以把它当作是一颗完全二叉树。


最大堆:堆里每一个父亲节点大于它的子女节点。

最小堆:堆里每一个父亲节点小于它的子女节点。

如图就是一个最大堆:

wKioL1cbOTSjDiLRAAAZq4jMjWY012.png

实现代码时我的测试序列是:int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 };

我们把它的图画出来,便于分析。

wKioL1cbVunRJvBdAABYpvWkEaw905.png

我们来实现如何将一个数组中的序列转变为最大堆。

若我们知道最大堆的代码后,只需将代码稍微修改一下就可以变成最小堆的代码。或者,我们可以用仿函数来提高代码的复用性。

实现代码如下:

建立头文件heap.hpp

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;#include<assert.h>#include<vector>template <class T>class Heap{public:    Heap()        :_a(NULL)    {}    //构造堆:先把各个元素接收到,再根据堆的特点将元素调整    Heap(const T* array, size_t size)    {        _a.reserve(size);        for (size_t i = 0; i < size; i++)        {            _a.push_back(array[i]);        }        //建堆        int Size = size;        for (int j = (_a.size() - 2) / 2; j>=0; j --)        {            _AdjustDown(j, Size);        }    }    //拷贝构造    Heap(const vector<T>& vec)        :_a(NULL)    {        _a.reserve(vec.size());        for (size_t i = 0; i < size; i++)        {            _a.push_back(vec[i]);        }    }    //插入一个元素x:先插入到顺序表中,再根据具体元素大小向上调整确定插入元素的位置    void Push(const T& x)    {        _a.push_back(x);        _AdjustUp(_a.size() - 1);    }    //删除根节点    void Pop()    {        size_t size = _a.size();        assert(size > 0);//防御式编程,确定是否可以删除元素        swap(_a[0], _a[size - 1]);//若直接删除堆的根节点,则会使堆结构紊乱        _a.pop_back();//将根节点与堆的最后一个节点交换位置,此时再对元素删除,以及将其调整于合适位置        size = _a.size();        _AdjustDown(0,size);    }    //访问堆的根节点    T& GetTop()    {        size_t size = _a.size();        assert(size > 0);        return _a[0];    }    //将根节点向下调整    void _AdjustDown(size_t parent,size_t size)    {        size_t child = 2 * parent + 1;        while (child<size)        {            if (child+1 < size && _a[child] < _a[child + 1])            {                child++;            }            if (_a[child] > _a[parent])            {                swap(_a[child], _a[parent]);                parent = child;                child = 2 * parent + 1;            }            else            {                break;            }        }            }    //向上调整    void _AdjustUp(int child)    {        //无论插节点后为左子树还是右子树,都可用(child-2)/2计算出此时父节点的下标        int parent = (child - 1) / 2;        int size = _a.size();//size用int,若用size_t循环条件且为>=0则死循环        while (child>0)//当child=0,说明此时已经到根节点位置,无需继续上调        {            //向上调整时,无需看左右节点哪个值大,只需要看是否父节点<根节点            if (_a[child]>_a[parent])            {                swap(_a[child], _a[parent]);                child = parent;                parent = (child-1)/2;            }            else            {                break;            }        }    }    bool Empty()    {        size_t size = _a.size();        assert(size >= 0);        return size == 0;    }    size_t Size()    {        size_t size = _a.size();        assert(size >= 0);        return size;    }            void PrintHeap()    {        cout << "堆的序列为:" << endl;        for (int i = 0; i < Size(); i++)        {            cout << _a[i] << "  ";        }        cout << endl;    }private:    vector<T> _a;};


建立源文件heap.cpp

#define _CRT_SECURE_NO_WARNINGS 1#include "heap.hpp"void Test(){    int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 };    Heap<int> h1(a, sizeof(a) / sizeof(a[0]));    Heap<int> h2(h1);    cout<<h1.GetTop()<<endl;    cout << h1.Size() << endl;    h1.Push(20);    cout << h1.GetTop() << endl;    h1.Pop();    cout << h1.Size() << endl;}int main(){    Test();    system("pause");    return 0;}


关于size(),GetTop()等函数我们可以通过测试函数Test()写出适当的测试用例来测试。


本文出自 “Han Jing's Blog” 博客,请务必保留此出处http://10740184.blog.51cto.com/10730184/1767076

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子在哈尔滨户口在外地医保怎么办 椒江二桥通行证被扣走了怎么办 住建委查到买房材料不真怎么办 房子租出去被别人又租出去了怎么办 在成都乘出租车房产证掉了怎么办 电信不限量卡限网速了怎么办 only实体店换货没有小票怎么办 运管所包车单不给盖章怎么办 上海留学生落户过了取号时间怎么办 电信固话怎么办才能显示自己公司 日本跟团签证没有资产证明怎么办 摇号手机号换了密码忘了怎么办 小客车摇号的账号密码忘了怎么办 去银行交违章罚款单子丢了怎么办 我的身份证被别人办了信用卡怎么办 北京驾驶证在深圳扣了分怎么办 c照一次被扣12分怎么办 教师资格证认定申请表填错了怎么办 外地车在北京违章没有牡丹卡怎么办 护士辞职了原单位不给延续怎么办 护士证注册的单位倒闭了怎么办 护士证注册的医院倒闭了怎么办 显示发货了但没物流信息怎么办 考科目三被别人举报了怎么办 科目一考了5没过怎么办 常州c1驾驶证满了12分怎么办 预约科目三成功后没交钱怎么办 预约成功后驾校不提交档案怎么办 c2刚满一年的驾照扣12分怎么办 怀孕6个月咳嗽很厉害怎么办 家门口有电线杆影响我建楼房怎么办 卡丢了不知道卡号怎么办 驾考网上预约用户被锁定了怎么办 人才中心拿出来的户口掉了怎么办 父母是南京集体户孩子没户口怎么办 二建挂靠中介单位不给证怎么办 小包工头遇到工人在工地摔伤怎么办 外地人买了城中村的房子改造怎么办 深圳社保怀孕了产检异地怎么办 成都公租房租满6年怎么办 二建审核资料如果照片丢失怎么办