【数据结构】堆的实现(包括:默认成员函数,插元素push,删元素pop,访问根节点top,判空,大小)
来源:互联网 发布:阴线买入指标公式源码 编辑:程序博客网 时间:2024/06/03 03:36
在数据结构里,堆是一类很重要的结构。堆结构是一组数组对象,我们可以把它当作是一颗完全二叉树。
最大堆:堆里每一个父亲节点大于它的子女节点。
最小堆:堆里每一个父亲节点小于它的子女节点。
如图就是一个最大堆:
实现代码时我的测试序列是:int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 };
我们把它的图画出来,便于分析。
我们来实现如何将一个数组中的序列转变为最大堆。
若我们知道最大堆的代码后,只需将代码稍微修改一下就可以变成最小堆的代码。或者,我们可以用仿函数来提高代码的复用性。
实现代码如下:
建立头文件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
- 【数据结构】堆的实现(包括:默认成员函数,插元素push,删元素pop,访问根节点top,判空,大小)
- 堆的实现(堆的建立及push、pop元素)
- 【C++】容器适配器实现队列Queue的各种功能(入队、出队、判空、大小、访问所有元素等)
- 【C++】容器适配器实现栈Stack的各种功能(入栈、出栈、判空、大小、访问所有元素等)
- 数据结构与算法-实验2-自定义栈,并实现push、pop、改栈顶元素、取栈顶元素
- 用固定大小的堆查找Top N个元素
- 链队列、循环队列的实现(初始化、出队、入队、取队头元素、判空)
- 堆的push,pop数组实现(挑战程序设计竞赛)
- 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)。
- 定义栈的数据结构,要求添加一个 min 函数,能够得到栈的最小元素。要求函数 min、push 以及 pop 的时间复杂度都是 O(1)。
- 定义栈的数据结构, 要求添加一个 min 函数, 能够得到栈的最小元素。 要求函数 min、 push 以及 pop 的时间复杂度都是 O(1)
- 一个栈,只提供push,pop,top,empty四种操作(这四种操作就是C++标准里的操作),对该栈的元素进行排序。
- 一个栈,只提供push,pop,top,empty四种操作(这四种操作就是C++标准里的操作),对该栈的元素进行排序
- 【数据结构】二叉树的实现(如:默认成员函数、(叶子)节点数、深度、四种遍历)
- 【数据结构】广义表的默认成员函数、深度、大小、打印
- DOM(包括获取元素节点的方法以及获取和设置元素节点的属性)
- 用栈实现队列的push、top和pop
- 堆(stack) 之 c 和 c++模板实现(空类默认成员函数 初谈引用 内联函数)
- 【C语言】str类与men库函数的实现(如:strcpy,strcmp,strstr,strcat,memmove,memcpy)
- 【数据结构】二叉树的实现(如:默认成员函数、(叶子)节点数、深度、四种遍历)
- 【数据结构】二叉树(前、中、后)序遍历的递归与非递归算法
- mfc获取其它程序窗口句柄
- /var/spool/postfix/maildrop/ 中有大量的文件
- 【数据结构】堆的实现(包括:默认成员函数,插元素push,删元素pop,访问根节点top,判空,大小)
- Android平台Native开发与JNI机制详解
- Java之IO操作总结
- 【数据结构】优先级队列的实现(适配器模式)
- 【数据结构】找出N个数据中最大的前k个数据(利用堆排序)
- 【数据结构】将一组数据升序排序(利用堆排序)
- 【C语言】静态顺序表的实现(包括头插、头删、尾插、尾删、查找、删除指定位置)
- 【数据结构】哈希表的线性探测算法
- 【数据结构】处理哈希冲突的开链法(哈希桶)算法实现