堆排序
来源:互联网 发布:商品数据库表结构 编辑:程序博客网 时间:2024/05/16 18:58
堆的基本操作参考文章:堆的基本操作
对于小根堆来说,一般的思路是每次删除最小值,执行N次删除;每次将删除的元素拷贝到一个新的数组,那么新数组将按照从小到大的顺序排列。这里的主要问题是空间的:使用新数组,使存储空间增加了一倍。
一个技巧是:每次删除一个堆元素,堆大小会减少1。那么位于堆最后的那个空间可以用来存放刚刚被删除的元素。按照这种思路,不用额外的空间即可完成排序。
对小根堆,该方式排序完的数组是递减的,那么,如果我们建立堆时用大根堆,则该方式得到的排序结果是递增的。
堆排序中用到了下滤操作,因为堆排序其实就是堆删除的一系列操作,而堆的删除操作会下滤,参考二叉堆的插入删除等操作C++实现
在移动堆元素的时候(AdjustHeap函数中),用到了一个技巧来减少交换元素的次数,参考插入排序和希尔排序,这里不再赘述。
/*(大根)堆排序,花费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];elsebreak;}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);}
0 0
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- 第三章 cas简单数据库认证配置
- 最简单的linux内核模块
- 【hall定理】一个关于二分图的问题
- Linux中断实现浅析
- 黑马程序员——内部类不能有静态的成员的原因
- 堆排序
- snprintf的使用
- Weblogic12.1.3集群管理手册(集群中的通信机制)
- 肠炎的危害有哪些?
- 二手车行业的风必须要去催生,两个最重要的点是时机和交易效率
- MongoDB资料大全
- 帮你深入理解OAuth2.0协议
- lua脚本基础语法
- linux驱动之按键驱动