学习这一章节之后,自己试着实现了以下:
数据结构与算法之美:28 | 堆和堆排序:为什么说堆排序没有快速排序快?
很多地方处理的比较仓促:
#include <iostream>
#include <vector>
using namespace std;
//大顶堆(基于vector)
template<class T>
class Heap{
public:
Heap(); //默认构造
Heap(int cap); //构造大小为cap的堆
Heap(vector<T> &vec, int len); //从数组vec构造一个堆
int size() const;
int maxSize() const;
bool empty() const;
void push(T value); //插入新元素
void pop(); //删除堆顶元素
const T& top() const; //获取堆顶元素(最大值或者优先级最高的值)
void print();//打印
//对堆内的数据进行排序,返回一个排序后的数组
//不改变原有的堆
vector<T> sort();
private:
void heapify(vector<T> &vec, int count, int i); //自上而下堆化
void swap(vector<T> &vec, int i, int j); //元素交换
vector<T> data; //底层是数组
int count = 0; //元素个数
int capacity; //容量
};
template<class T>
Heap<T>::Heap(){
capacity = 10; //默认容量10
//count = 0;
data.resize(capacity + 1); //分配至少能容纳capacity+1个元素的空间(元素下标从1开始)
}
template<class T>
Heap<T>::Heap(int cap){
capacity = cap;
//count = 0;
data.resize(capacity + 1); //分配至少能容纳capacity+1个元素的空间(元素下标从1开始)
}
/*这儿使用的是第一种思路建堆(就是简单地不停插入元素)
template<class T>
Heap<T>::Heap(vector<T> &vec, int len){
capacity = len;
//count = 0;
data.resize(capacity + 1); //分配至少能容纳capacity+1个元素的空间(元素下标从1开始)
for (int i = 0; i < len; ++i) push(vec[i]);
}
*/
//使用第二中方式建堆
//从一个数组直接建堆
template<class T>
Heap<T>::Heap(vector<T> &vec, int len){
capacity = len;
data.resize(capacity + 1); //分配至少能容纳capacity+1个元素的空间(元素下标从1开始)
for (int i = 1; i <= capacity; ++i){ //先将元素拷贝到data(data下标从1开始)
data[i] = vec[i - 1];
++count;
}
for (int i = count/2; i >= 1; --i) heapify(data, count, i);//建堆,从第一个非叶子结点开始自下而上
}
template<class T>
int Heap<T>::size() const {
return count;
}
template<class T>
int Heap<T>::maxSize() const {
return capacity;
}
template<class T>
bool Heap<T>::empty()const {
return count == 0;
}
template<class T>
void Heap<T>::push(T value){
if (count >= capacity){
cerr << "heap已满,push失败!" << endl;
return;
}
++count;
data[count] = value;
int i = count;
while (i / 2 > 0 && data[i] > data[i / 2]){//自下而上堆化
swap(data, i, i / 2);
i = i / 2;
}
}
template<class T>
void Heap<T>::pop(){
if (count == 0){
cerr << "heap为空,无法pop()!" << endl;
}
else{
data[1] = data[count];
--count;
heapify(data, count, 1);
}
}
template<class T>
const T &Heap<T>::top()const{
if (count == 0){
cerr << "heap为空,无法访问top()!" << endl;
}else
return data[1];
}
template<class T>
void Heap<T>::print(){
for (int i = 1; i <= count; ++i)
cout << data[i] << " ";
cout << endl;
}
template<class T>
vector<T> Heap<T>::sort(){
auto vec = data;
//vec.erase(vec.begin());
int n = count;
while (n > 1){
swap(vec, n, 1);
--n;
heapify(vec, n, 1);
}
vec.erase(vec.begin());// //因为之前元素是从下标1开始的
return vec;
}
template<class T>
void Heap<T>::heapify(vector<T> &vec, int count, int i){
while (true){
int maxPos = i;
if (2*i <= count && vec[i] < vec[2*i]) maxPos = 2*i;
if (2*i+1 <= count && vec[maxPos] < vec[2*i+1]) maxPos = 2*i+1;
if (i == maxPos) break;
swap(vec, i, maxPos);
i = maxPos;
}
}
template<class T>
void Heap<T>::swap(vector<T> &vec, int i, int j){
auto tmp = vec[i];
vec[i] = vec[j];
vec[j] = tmp;
}
另外堆排序还可以参考这儿: