MIT:算法导论——4.1.排序和顺序统计量_堆排序
2014-06-05 21:16
627 查看
【排序问题】
输入:一个n个数的序列<a1, a2, ..., an>。
输出:输入序列的一个排列(重排)<a1', a2', ..., an'>,使得a1' <= a2' <= ... an'。
输入序列通常是一个n元数组,尽管它可以用链表等其他方式描述。
【为什么要排序】
很多计算机科学家认为 排序是算法研究中最基础的问题。
【插入排序】
由于其内层循环非常紧凑,对于 小规模输入,插入排序是一种非常快的原址排序算法。
如果输入数组中仅有常数个元素需要在排序过程中存储在数组之外,则成排序算法是原址的(in place)。
【空间原址性】任何时候都只需要常数个额外的元素空间存储临时数据。
【比较排序算法】
插入排序、归并排序、快速排序、堆排序等都是比较排序算法——
通过对元素进行比较操作 来确定输入数组的有序次序。
比较排序算法的排序n个元素的最坏情况运行时间的下界为Ω(nlgn)。
【线性时间排序】
采用比较操作之外的方法来获得输入序列有序次序的信息,以打破Ω(nlgn)的下界,以获得线性时间O(n)。
计数排序:O(n+k),数值集合为{0, 1, ..., k};当k=O(n)时,可以获得线性运行时间。
基数排序:O(d(n+k)),每个整数有d位,每个数字可能取k值;当d是常数且k=O(n)时,其运行时间为线性的。
桶排序:O(n),当n个实数在半开区间[0, 1)内服从均匀分布的n个实数,桶排序的平均情况运行时间为O(n)。
【顺序统计量】
一个n个数的集合的 第i个顺序统计量就是集合中第i小的数。
当不知道其顺序,先排序再输出第i个元素的方式,运行时间为Ω(nlgn)。
****************************************************
【堆】
A[1...n],树的根结点为为A[1],这样容易计算得到父节点、左孩子、右孩子。
在堆排序的好的实现中,下面这三个函数通常是以宏或者内联函数的方式实现的:
#define PARENT( i ) ( i >> 1 )
#define LEFT( i ) ( i << 1 )
#define RIGHT( i ) ( i << 1 + 1)
【最大堆】A[PARENT( i )] >= A[i]
【最小堆】A[PARENT( i )] <= A[i]
最大堆性质:
(1)堆中最大元素在根结点中;且任一子树中,该子树包含的所有结点的值都不大于该子树根结点的值。
(2)含n个元素的堆的高度为lgn下取整。
(3)当用数组存储n个结点时,最后一个非叶节点为[n/2」 = PARENT( n )。
输入:一个n个数的序列<a1, a2, ..., an>。
输出:输入序列的一个排列(重排)<a1', a2', ..., an'>,使得a1' <= a2' <= ... an'。
输入序列通常是一个n元数组,尽管它可以用链表等其他方式描述。
【为什么要排序】
很多计算机科学家认为 排序是算法研究中最基础的问题。
【插入排序】
由于其内层循环非常紧凑,对于 小规模输入,插入排序是一种非常快的原址排序算法。
如果输入数组中仅有常数个元素需要在排序过程中存储在数组之外,则成排序算法是原址的(in place)。
【空间原址性】任何时候都只需要常数个额外的元素空间存储临时数据。
【比较排序算法】
插入排序、归并排序、快速排序、堆排序等都是比较排序算法——
通过对元素进行比较操作 来确定输入数组的有序次序。
比较排序算法的排序n个元素的最坏情况运行时间的下界为Ω(nlgn)。
【线性时间排序】
采用比较操作之外的方法来获得输入序列有序次序的信息,以打破Ω(nlgn)的下界,以获得线性时间O(n)。
计数排序:O(n+k),数值集合为{0, 1, ..., k};当k=O(n)时,可以获得线性运行时间。
基数排序:O(d(n+k)),每个整数有d位,每个数字可能取k值;当d是常数且k=O(n)时,其运行时间为线性的。
桶排序:O(n),当n个实数在半开区间[0, 1)内服从均匀分布的n个实数,桶排序的平均情况运行时间为O(n)。
【顺序统计量】
一个n个数的集合的 第i个顺序统计量就是集合中第i小的数。
当不知道其顺序,先排序再输出第i个元素的方式,运行时间为Ω(nlgn)。
****************************************************
【堆】
A[1...n],树的根结点为为A[1],这样容易计算得到父节点、左孩子、右孩子。
在堆排序的好的实现中,下面这三个函数通常是以宏或者内联函数的方式实现的:
#define PARENT( i ) ( i >> 1 )
#define LEFT( i ) ( i << 1 )
#define RIGHT( i ) ( i << 1 + 1)
【最大堆】A[PARENT( i )] >= A[i]
【最小堆】A[PARENT( i )] <= A[i]
最大堆性质:
(1)堆中最大元素在根结点中;且任一子树中,该子树包含的所有结点的值都不大于该子树根结点的值。
(2)含n个元素的堆的高度为lgn下取整。
(3)当用数组存储n个结点时,最后一个非叶节点为[n/2」 = PARENT( n )。
#if 1 #include <iostream> using namespace std; #define PARENT( i ) ( i >> 1 ) #define LEFT( i ) ( i << 1 ) #define RIGHT( i ) ( i << 1 + 1) //(1)MAX-HEAPIFY过程:其时间复杂度为O(lgn),它是维护最大堆性质的关键。 template<typename T> void max_heapify( T a[], int i, int heap_size ) {// 可以将heap_size集成到包含T a[]的堆类中 int c; T data; data = a[i]; c = LEFT( i ); while( c <= heap_size ){ if( c < heap_size && a[c] < a[c+1] ) ++c; if( data >= a[c] ) break; a[PARENT(c)] =a[c];// 自己编程遗忘了这一步 c = LEFT( c ); } a[PARENT(c)] = data; } //(2)BUILD-MAX-HEAP过程:具有线性时间复杂度;O(nlgn)-->O(n) // 功能是从无序的输入数据数组中构造一个最大堆。 template<typename T> void build_max_heap( T a[], int heap_size ) { if( a == NULL || heap_size <= 1 ) return; for( int i = PARENT( heap_size ); i >= 1; --i ){ max_heapify( a, i, heap_size ); } } //(3)HEAPSORT过程:其时间复杂度为O(nlgn),功能是对一个数组进行原址排序 template<typename T> void heap_sort( T a[], int heap_size ) { build_max_heap( a, heap_size ); for( int i = heap_size; i >= 2; --i ){ #if defined( TEST ) for( int j = 1; j <= heap_size; ++j ) cout << a[j] << " "; cout << endl; #endif T tmp = a[1]; a[1] = a[i]; a[i] = tmp; max_heapify( a, 1, i - 1 ); //max_heapify( a, i, heap_size ); } } //(4)MAX-HEAP-INSERT template<typename T> void max_heap_insert( T a[], int heap_size, int max_size, T& data ) { if( heap_size == max_size ) return;// throw out_of_bounds("NoMem"); int c = ++heap_size; while( c != 1 && a[PARENT(c)] < a[c] ){ a[c] = a[PARENT(c)]; c = PARENT(c); } a[c] = data; } int main( void ) { int a[] = { 0, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 }; heap_sort<int>( a, sizeof(a) / sizeof(int) - 1 ); for( int i = 1; i < sizeof( a ) / sizeof( int ); ++i ) cout << a[i] << " "; cout << endl; } #endif
相关文章推荐
- 插入排序,合并排序,堆排序,快速排序,计数排序的实现(算法导论)
- 排序和顺序统计量(算法导论)
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- MIT:算法导论——4.2快速排序 以及 排序算法时间复杂度分析
- 算法学习笔记----第二部分:排序和顺序统计量----第6章、堆排序
- MIT:算法导论——1.算法分析——插入排序 vs 二路归并排序
- MIT:算法导论——6.中位数和顺序统计量:随机快排应用==>随机选择
- 书山有路之学习算法导论(二)--排序和顺序统计量
- 算法学习笔记----第二部分:排序和顺序统计量----第6章、堆排序
- 【算法导论】排序 (二):堆排序
- 读书笔记 算法导论 快速排序 QuickSort 使用最后一个元素作为pivot
- 算法入门--堆排序(最大堆,从小到大排序)
- 【算法导论 第7章 快速排序】
- 基础算法之四--排序:之堆排序
- 算法导论:插入排序
- 堆排序(算法导论)
- [算法导论] 6.4堆排序
- 【算法导论】 2.3合并排序
- 算法导论-7-6 对区间的模糊排序
- 【算法导论】第二十七章 排序网络