堆排序(Heap Sort)
2012-09-26 20:44
260 查看
维基百科:http://zh.wikipedia.org/wiki/堆排序
1、基本知识
二叉堆一般用数组来表示,我们可以把它视为一颗完全二叉树。数据结构中学习树这一章节时,我们知道完全二叉树可以用数组来存储。
堆的定义:
(1)大根堆:父节点的值大于等于孩子结点的值
(2)小根堆:父节点的值小于等于孩子结点的值
父节点和孩子结点下标的计算
(1)假设用数组A[1..n]来存储完全二叉树,即下标从1开始
结点i的父节点:i/2 (向下取整)
结点的左孩子结点:2*i(如果存在)
结点的右孩子结点:2*i + 1(如果存在)
(2)假设用数组A[0..n-1]来存储完全二叉树,即下标从0开始
结点i的父节点:(i-1)/2
结点i的左孩子结点: 2 * i +1(如果存在)
结点的右孩子结点:2 * i + 2(如果存在)
2、算法思想
以对数组进行升序排序为例,可以把数组建为一个大根堆,然后不断输出堆顶元素, 并调整堆,直至输出所有元素。这里采取的是数组首元素和尾元素交换,也就是把最大元置于数组尾部,每一次都可以确定一个元素的最终位置,显然堆排序算法属于原地排序。
3、代码实现
下面的代码是根据算法导论中的伪代码编写的,代码中有详细的注释。
(1)对于大小为n的数组,堆的高度为lgn,
(2)调整函数maxHeapify的复杂度为O(h),即O(lgn)。
(3)heapSort中循环执行O(n)次,因而算法复杂度为O(nlgn)
算法时最坏情况下和平均情况下的时间复杂度都为O(nlogn),堆排序是渐进最优的排序算法。
参考资料:
[1]算法导论(第2版)
[2]严蔚敏《数据结构(C语言版)》
1、基本知识
二叉堆一般用数组来表示,我们可以把它视为一颗完全二叉树。数据结构中学习树这一章节时,我们知道完全二叉树可以用数组来存储。
堆的定义:
(1)大根堆:父节点的值大于等于孩子结点的值
(2)小根堆:父节点的值小于等于孩子结点的值
父节点和孩子结点下标的计算
(1)假设用数组A[1..n]来存储完全二叉树,即下标从1开始
结点i的父节点:i/2 (向下取整)
结点的左孩子结点:2*i(如果存在)
结点的右孩子结点:2*i + 1(如果存在)
(2)假设用数组A[0..n-1]来存储完全二叉树,即下标从0开始
结点i的父节点:(i-1)/2
结点i的左孩子结点: 2 * i +1(如果存在)
结点的右孩子结点:2 * i + 2(如果存在)
2、算法思想
以对数组进行升序排序为例,可以把数组建为一个大根堆,然后不断输出堆顶元素, 并调整堆,直至输出所有元素。这里采取的是数组首元素和尾元素交换,也就是把最大元置于数组尾部,每一次都可以确定一个元素的最终位置,显然堆排序算法属于原地排序。
3、代码实现
下面的代码是根据算法导论中的伪代码编写的,代码中有详细的注释。
#include <cstdlib> #include <iostream> using namespace std; //父节点下标 int parent(int i) { return (i - 1)/2; } //左孩子下标 int leftChild(int i) { return (2 * i + 1); } //右孩子下标 int rightChild(int i) { return (2 * i + 2); } /*调整下标为i的结点的位置,使以其为根的子树为大根堆 假定该函数被调用时,以left(i)和right(i)为根的两棵二叉树都是大根堆 */ template<class T> void maxHeapify(T* a, int i, int heapSize) { int largest = -1; //记录a[i]和其子女(如果存在)中最大者小标 int left = leftChild(i); int right = rightChild(i); if(left < heapSize && a[left] > a[i]) { largest = left; } else { largest = i; } if(right < heapSize && a[right] > a[largest]) { largest = right; } if(i != largest) { swap(a[i], a[largest]); maxHeapify(a,largest,heapSize); } } //把一个数组构建为大根堆 template<class T> void buildMaxHeap(T* a, int heapSize) { int i = heapSize/2 -1; //最后一个非叶子结点下标 for(; i>=0; i--) { maxHeapify(a, i, heapSize);//从最后一个非叶子结点开始自底向上调整堆 } } //堆排序 template<class T> void heapSort(T* a, int n) { int heapSize = n; buildMaxHeap(a, heapSize);// // 把最大元素(堆顶元素)和堆尾元素交换,堆的大小减1,从堆顶开始自顶向下调整堆 //重复以上操作直到堆的大小为1 for(int i=n-1; i>0; i--) { swap(a[0],a[i]); heapSize--; maxHeapify(a,0,heapSize); } } int main(int argc, char *argv[]) { int n; int *a = NULL; while(cin>>n && n > 0) { a = new int ; for(int i=0; i<n; i++) { cin>>a[i]; } heapSort(a,n); for(int i=0; i<n; i++) { cout<<a[i]<<" "; } cout<<endl<<endl; delete [] a; } system("PAUSE"); return EXIT_SUCCESS; }4、复杂度分析
(1)对于大小为n的数组,堆的高度为lgn,
(2)调整函数maxHeapify的复杂度为O(h),即O(lgn)。
(3)heapSort中循环执行O(n)次,因而算法复杂度为O(nlgn)
算法时最坏情况下和平均情况下的时间复杂度都为O(nlogn),堆排序是渐进最优的排序算法。
参考资料:
[1]算法导论(第2版)
[2]严蔚敏《数据结构(C语言版)》
相关文章推荐
- 堆排序(heapsort)
- HeapSort(堆排序)入门
- C语言-数据结构-堆排序(heap sort)-源代码
- 堆排序(heap_sort)
- HeapSort(堆排序 C++)
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 堆排序练习(Heap Sort)
- 一天一排序之“堆排序(heapsort)”
- 算法分析之——heap-sort堆排序
- 排序算法 之 堆排序 HeapSort
- 堆排序(Heapsort)之Java实现
- HeapSort——堆排序实现(算法类)
- 堆排序_heap_sort
- PHP实现排序算法----堆排序(Heap Sort)
- 堆--堆排序--heap--heap_sort
- HeapSort 堆排序
- 堆排序(Heap Sort)
- 堆排序(HeapSort)
- 算法----堆排序(heap sort)
- 堆排序(Heap Sort) 算法实现 C语言版