归并排序,堆排序和快速排序都有一个性质:在排序的最终结果中,各元素的次序依赖于它们之间的比较.我们把这类排序算法称为比较排序.任何比较排序在最坏情况下都要经过nlgn次比较.因此,归并排序和堆排序是渐近最优的,并且任何已知的比较排序最多就是在常数因子上优于它们.
8.1 排序算法的下界
定理8.1:在最坏情况下,任何比较排序算法都需要做"ou"(nlgn)次比较.具体证明看书上的论述.
推论8.2:堆排序和归并排序都是渐近最优的比较排序算法.
8.2 计数排序
计数排序假设n个输入元素中的每一个都是在0到k区间内的一个整数,其中k为某个整数.当k=O(n)时,排序的运行时间为n.
计数排序的基本思想是:对每一个输入元素x,确定小于x的元素个数.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void counting_sort( int A[], int B[], int len, int k )
{
int i = 0;
int *C = ( int * )malloc( sizeof( int ) * k );
memset( C, 0, sizeof( int ) * k );
for ( i = 0; i < len; i++ ){
C[ A[ i ] ] += 1;
}
for ( i = 1; i < k; i++ ){
C[ i ] += C[ i - 1 ];
}
for ( i = 0; i < k; i++ ){
C[ i ] -= 1; //下标索引从0开始
}
for ( i = len - 1; i >= 0; i-- ){
B[ C[ A[ i ] ] ] = A[ i ];
C[ A[ i ] ] -= 1;
}
}
int main( void )
{
int i = 0;
int A[ 8 ] = { 2, 5, 3, 0, 2, 3, 0, 3 };
int B[ 8 ];
memset( B, 0, sizeof( int ) * 8 );
counting_sort( A, B, 8, 6 );
for ( i = 0; i < 8; i++ ){
printf("%d ", B[ i ] );
}
return 0;
}
要注意一点:数组的下标是从0开始的,而算法书上都是从1开始的,所以代码要经过某点修改:
程序输出:
计数排序的一个重要性质就是它是稳定的:具有相同值的元素在输出数组中的相对次序与它们在输入数组中的相对次序相同.也就是说,对两个相同的数来说,在输入数组中先出现的数,在输出数组中也位于前面.通常,这种稳定性只有当进行排序的数据还附带卫星数据时才比较重要.计数排序的稳定性很重要的另一个原因是:计数排序经常会被用作基数排序算法的一个子过程.
8.3 基数排序
将计数排序重复的一种排序方式
8.4 桶排序
类似于计数排序,但是假设输入数据服从均匀分布.
思考题大量包含数学知识,先不做.....