堆的基本操作参考文章:[堆的基本操作](http://blog.csdn.net/u013074465/article/details/46741421)
对于小根堆来说,一般的思路是每次删除最小值,执行N次删除;每次将删除的元素拷贝到一个新的数组,那么新数组将按照从小到大的顺序排列。这里的主要问题是空间的:使用新数组,使存储空间增加了一倍。
一个技巧是:每次删除一个堆元素,堆大小会减少1。那么位于堆最后的那个空间可以用来存放刚刚被删除的元素。按照这种思路,不用额外的空间即可完成排序。
对小根堆,该方式排序完的数组是递减的,那么,如果我们建立堆时用大根堆,则该方式得到的排序结果是递增的。
堆排序中用到了下滤操作,因为堆排序其实就是堆删除的一系列操作,而堆的删除操作会下滤,参考[二叉堆的插入删除等操作C++实现](http://blog.csdn.net/u013074465/article/details/42028473)
在移动堆元素的时候(AdjustHeap函数中),用到了一个技巧来减少交换元素的次数,参考[插入排序和希尔排序](http://blog.csdn.net/u013074465/article/details/42043665),这里不再赘述。
~~~
/*
(大根)堆排序,花费O(NlogN)。
*/
template<typename T>
void HeapSort(vector<T>& a) {
int i;
//先建立大根堆,该操作花费O(N)
for (i = a.size() / 2; i >= 0; --i) {
AdjustHeap(a, i, a.size());
}
//将要删除的元素放入堆末尾的空间(交换根元素和尾元素),
//这样不需要额外的空间。
for (i = a.size() - 1; i > 0; --i) {
T tmp = a[i];
a[i] = a[0];
a[0] = tmp;
/*
每次删除时,根元素与根末尾元素交换了,在位置0处下滤。
由于不断从堆中删除,因此堆大小不断减小,为i
*/
AdjustHeap(a, 0, i);
}
}
//该函数是堆操作中的下滤操作
template<typename T>
void AdjustHeap(vector<T>&a, int pos, int n) {
int pos_child;
T tmp;
for (tmp = a[pos]; (pos * 2 + 1) < n; pos = pos_child) {
pos_child = 2 * pos + 1;
if (pos_child != n -1 && a[pos_child] < a[pos_child + 1])
pos_child++;
if (tmp < a[pos_child])
a[pos] = a[pos_child];
else
break;
}
a[pos] = tmp;
}
//只是一个打印元素的函数
template<typename T>
void PrintValue(vector<T>& a) {
vector<T>::iterator iter = a.begin();
while (iter != a.end()) {
cout << *iter++ << " ";
}
cout << endl;
}
int main() {
int value;
vector<int> ivec;
while (cin >> value)
ivec.push_back(value);
HeapSort<int>(ivec);
PrintValue(ivec);
}
~~~
![](https://box.kancloud.cn/2016-06-07_575683a0cc270.jpg)
- 前言
- Josephus约瑟夫问题及其变种
- 链表的常见实现
- 二叉树遍历、插入、删除等常见操作
- 二叉堆的插入删除等操作C++实现
- 插入排序和希尔排序
- 堆排序
- 归并排序及其空间复杂度的思考
- 快速排序的几种常见实现及其性能对比
- 红黑树操作及实现
- 整数的二进制表示中1的个数
- 位操作实现加减乘除四则运算
- 冒泡排序的改进
- 直接选择排序
- 不借助变量交换两个数
- 基础排序算法总结
- AVL树(Adelson-Velskii-Landis tree)
- avl树的C++实现
- 动态规划之钢条分割
- hash函数的基本知识
- 动态规划:求最长公共子串/最长公共子序列
- 最长递增子序列
- 称砝码问题
- 汽水瓶
- 字符串合并处理(二进制位的倒序)
- 动态规划:计算字符串相似度
- m个苹果放入n个盘子
- 生成k个小于n的互不相同的随机数
- 栈和队列的相互模拟
- 字符串的排列/组合
- KMP(Knuth-Morris-Pratt)算法
- n个骰子的点数
- 位运算的常见操作和题目