数据结构:堆(heap)
来源:互联网 发布:安卓模拟器知乎 编辑:程序博客网 时间:2024/06/16 10:36
堆就是一种完全二叉树
堆可分为大堆和小堆
大堆:所有父节点大于子节点。
小堆:所有父节点小于子节点。
由于它是一棵完全二叉树,其元素之间没有空隙,所以我们可以用一个vector来表示它
我们可以根据需要选择创建大堆还是小堆,我们用仿函数实现这个功能
//大堆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& s, const T& b) { return a < b; }};
堆主要有两种算法:向上调整算法和向下调整算法
在进行插入操作时,我们使用向上调整算法:
而在进行删除操作时,使用向下调整算法:
代码实现:
#include<iostream> #include<vector> #include<assert.h> 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& s, const T& b) { return a < b; }};template<class T,class Compare = Greater<T>>class Heap{public: Heap() {} Heap(T* a, int n) { _a.reserve(n);//增容(可以直接拷贝数据) for (int i = 0; i < n; i++) { _a.push_back(a[i]); } //调整成堆 for (int j = (_a.size() - 2) / 2; j >= 0; --j) { //向下调整 _AjustDown(j); } } void Push(const T& x) { _a.push_back(x); _AjustUp(_a.size() - 1); } void Pop() { assert(!_a.empty()); swap(_a[0], _a[_a.size() - 1]); _a.pop_back(); _AjustDown(0); } const T& Top() { return _a[0]; } size_t Size() { return _a.size(); } bool Empty() { return _a.empty(); }protected: //push_heap算法:向上调整 void _AjustUp(int child) { assert(!_a.empty()); int parent = (child - 1) >> 1; while (child>0) { //如果孩子节点的值大于父节点的值 Compare com; if (com(_a[child] , _a[parent])) { swap(_a[child], _a[parent]); child = parent; parent = (child - 1) >> 1; } else { break; } } }protected: //pop_heap:向下调整算法 void _AjustDown(int root) { int parent = root; int child = parent * 2 + 1; while (child < _a.size()) { Compare com; if ((child + 1 < _a.size()) &&( _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; } } }private: vector<T> _a;};
测试:
void Test(){ int a[] = { 1, 6, 8, 2, 3, 5, 7, 4, 9 }; int len = sizeof(a) / sizeof(a[0]); Heap<int, Greater<int>> h(a, len); h.Top(); h.Push(25); h.Pop(); while (!h.Empty()) { cout << h.Top() << " "; h.Pop(); } cout << endl;}
那么,堆有什么应用呢?
1,TopK问题
在一大堆数字中找到K个最大或最小的数字。
在现实中,很多场景都类似于这样的问题,比如,选出一个专业某科成绩排名前K的同学等等。这个时候,我们就可以利用一个小堆来进行筛选,堆顶为最小元素,比堆顶大(或小)的则进堆,重新建成一个小堆。以此类推,便形成了一个有K个元素的小堆。
void TopK(int* arr, size_t k,int n){ Heap<int, Less<int>> hp(arr,k); for (size_t i = 0; i < n; i++) { if (arr[i] < hp.Top())//比堆顶数据大的则入堆 { hp.Push(arr[i]); hp.Pop();//取出堆顶数据 } }}int main(){ //Test(); int arr[1000]; int sz = sizeof(arr) / sizeof(arr[0]); for (size_t i = 0; i < sz; ++i) { arr[i] = rand() % 200; } arr[10] += 200; arr[20] += 200; arr[30] += 200; arr[40] += 200; arr[50] += 200; arr[60] += 200; arr[70] += 200; arr[80] += 200; TopK(arr, 8, sz); system("pause"); return 0;}
2,堆排
//堆排void AjustDown(int *a, size_t root, size_t n){ size_t parent = root; size_t child = parent * 2 + 1; while (child < n) { if ((child + 1 < n) && (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 HeapSort(int *a,int n){ assert(a); for (int i = (n-2)/2; i >= 0; i--) { AjustDown(a, i, n); } int end = n - 1; while (end > 0) { swap(a[0], a[end]); AjustDown(a, 0, end); --end; }}int main(){ int a[] = { 2, 4, 6, 7, 8, 9, 0, 5, 1, 3 }; int sz = sizeof(a) / sizeof(a[0]); HeapSort(a, sz); for (int i = 0; i < sz; i++) { cout << a[i] << " "; } cout << endl; system("pause"); return 0;}
阅读全文
0 0
- 【数据结构】堆(heap)
- 数据结构-堆(heap)
- 【数据结构】堆(heap)
- 数据结构-堆(Heap)
- 数据结构-堆(heap)
- 数据结构:堆(heap)
- 数据结构 之 二叉堆(Heap)
- 数据结构之堆(Heap)的实现
- 数据结构之Binary Heap(二叉堆)
- 【数据结构】堆 Heap
- 数据结构 《6》----堆 ( Heap )
- 数据结构-树-堆(heap)
- 数据结构之堆Heap
- 数据结构之堆(Heap)
- 数据结构:堆Heap
- 数据结构之堆(Heap)(9)
- 浅谈数据结构—堆(heap)
- 【数据结构-堆排序】堆排序 Heap Sort
- Numpy 使用教程 4
- Nginx作为七层负载均衡调度器
- NKOJ-3775 数列操作
- 【学习笔记八】- JS 冒泡与捕获(事件流+事件处理程序+事件对象)
- mybatis入门dao方式写URUD(二)
- 数据结构:堆(heap)
- iOS UITableView~delegate(代理方法)
- C语言文件读写
- web网站加速之CDN技术原理
- pip安装错误:ImportError: No module named 'pkg_resources'
- Numpy 使用教程 5
- 《C++ Primer》读书笔记第九章-1- 顺序容器概述 And 容器库概览
- Java程序逻辑控制,Java循环
- 有效处理Java异常三原则