堆实现及常见面试题
来源:互联网 发布:js获取当前时间显示 编辑:程序博客网 时间:2024/06/07 08:40
一、堆的概念:关键码的集合按完全二叉树的顺序存储方式存储在一维数组中,并满足:对于所有节点它的父节点关键码都大于子节点(或都小于它的子节点),这样的堆称为最大堆(或最小堆)。二、堆相关的问题1.简单实现一个堆 堆的建立、放入数据、删除数据、判断是否为堆2.TopK问题,求数组中最大的K个元素3.堆排序(实质是一个选择排序),一个数组的升序、降序 三、下面例子中,博主是以建最大堆的方式实现的堆,在实现TopK中需要建小堆,博主又另写了一个建小堆的函数。***Autually***, 这是一种较为笨的方法,可以实现一个仿函数,增加函数的复用性,这样建小堆建大堆就不用建不同的堆了。代码如下:
#pragma once#include <iostream>#include <vector>#define N 10000using namespace std;template<class T>class Heap{public: Heap() {} Heap(T* a, size_t n) { _a.reserve(n); for (size_t i = 0; i < n; i++) { _a.push_back(a[i]); } //建堆 for (int i = (_a.size() - 2) / 2; i >= 0; --i)//从倒数第一个非叶节点开始 { AdjustDown(i); } } HeapT(T* a, size_t k)//实现TopK建堆方式 { _a.reserve(k); for (size_t i = 0; i < k; i++) { _a.push_back(a[i]); } for (int i = (_a.size() - 2) / 2; i >= 0; --i)//建小堆 { AdjustDownL(i); } } void TopK(T* a) { for (size_t i = 100; i < N;) { if (_a[0] < a[i]) { _a[0] = a[i]; AdjustDownL(0); ++i; } else { ++i; } } } void HeapRiseSort(T* a, size_t k)//升序建大堆 降序降序建小堆 { _a.reserve(k); int end = k - 1; Heap(a, k);//建堆 while (end > 0) { swap(_a[0], _a[end]); end--; AdjustDown(0); //堆排序(升序),每次把堆顶数据放到数组后面,再利用前end个元素重新建大堆 } } void Print() { for (size_t i = 0; i < _a.size(); i++) { cout << _a[i] << " "; } cout << endl; } void Push(const T& x) { _a.push_back(x); AdjustUp(_a.size()-1); } void AdjustUp(int child) { int parent = (child - 1) >> 1; while (child != 0) { if (_a[child] > _a[parent]) { swap(_a[child], _a[parent]); child = parent; parent = (child - 1) >> 1; } else { break; } } } void Pop() { swap(_a[0], _a[_a.size() - 1]); _a.pop_back(); AdjustDown(0); } void AdjustDown(int root) { int parent = root; 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 = child * 2 + 1; } else { break; } } } void AdjustDownL(int root) { int parent = root; 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 = child * 2 + 1; } else { break; } } } int IsBHeap() { for (int i = _a.size() - 1; i >= 0; i++) { return _IsBHeap(i)==true;//为真返回1,假0 } }protected: bool _IsBHeap(int root) { int child = root; int parent = (child - 1) >> 1; while (child<_a.size()) { int large = child; if (child + 1<_a.size() && _a[child + 1]>_a[child]) { large = child + 1; } if (_a[large] < _a[parent]) { return true; } else { return false; } } return false; } vector<T> _a;};
测试用例:
#pragma once#include "Heap.h"void Heaptest(){ int arr[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 }; Heap<int>h1(arr, sizeof(arr)/sizeof(arr[0])); h1.Print(); h1.Pop(); h1.Print(); h1.Push(20); h1.Print(); h1.Push(2); cout << h1.IsBHeap() << endl;}void topKTest(){ int arr[N] = { 0 }; for (size_t i = 0; i < N; i++) { arr[i] = rand() % N; } arr[100] = 12000; arr[999] = 11145; arr[888] = 10008; arr[118] = 19999; arr[365] = 19880; arr[254] = 13444; arr[4579] = 14555; arr[1000] = 47839; arr[9992] = 19875; arr[1723] = 98345; HeapT<int>h1(arr, 10); h1.TopK(arr); h1.Print();}//堆排序实质上是一种选择排序,选出最大的与尾部数据交换,然后堆元素个数--,重新建堆,相当于没把刚刚选出的最大的数算在重新建的堆中void Heaptest(){ int arr[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 }; Heap<int>h1(arr, 10); h1.HeapRiseSort(arr,10); h1.Print();}
堆就讲到这里啦,之后会给大家补充仿函数和堆的相关知识,拜拜~
阅读全文
0 0
- 堆实现及常见面试题
- 常见面试题及基础
- 【javascript常见面试题】常见前端面试题及答案
- 常见面试题-memcpy()实现
- [各种面试题] 堆的实现
- java常见面试题及答案
- java 常见面试题及答案
- linux常见面试题及答案
- c#常见面试题及答案
- 链表基础及常见面试题
- 单链表常见面试题及答案
- 单链表常见面试题及答案
- struts常见面试题及解析
- ssh常见面试题及解析
- PHP常见面试题及答案
- 常见android面试题及答案
- 常见前端面试题及答案
- 前端常见面试题及方案解决
- angular指令心得(ng-model)
- codeforces 807A
- Java面试题【对象序列化】
- Linux Shell 数据重定向详解
- Hibernate(二)session详解
- 堆实现及常见面试题
- QSlider样式设计
- Oracle 数据库管理
- 1056. 组合数的和(15) PAT
- excel导出图片
- 微信JS-SDK图像接口的具体实现
- PHP异步
- linux系统中如何进入退出vim编辑器,方法及区别
- 使用IO流对文件进行读取功能