希尔排序是首批冲破二次效率的排序算法。主要利用了插入排序的以下特性:
1.对于已经排好序的数据,插入排序表现为O(N)。
2.插入排序能不能更快的找到每个元素的位置。(引入了增量序列)。
具体算法,谷歌一下吧。这里给出C和Java的实现。(代码已经用过很久了,可以直接拿来用,已泛型化)
注:增量序列来自公式:9 * pow(4, j) - 9 * pow(2, j) + 1 和 pow(4, j) - 3 * pow(2, j) + 1
C的实现:
/*
* shell sort functions implements file.
*
* @author chenxin
* @see http://www.webssky.com
*/
#include <stdlib.h>
//#include <stdio.h>
#include "jsort.h"
/*
* shell sort algorithm.
*
* @param *arr the pointer of the array to sort.
* @param len the length of the array.
*/
void shell_sort( void *a, size_t len, size_t size, compare_fn_t comp ) {
int gaps[] = {
1, 5,
19, 41,
109, 209, 505, 929,
2161, 8929,
16001, 36289, 64769,
146305, 260609, 587521, //1000th
1045505, 2354689, 4188161, 9427969,
16764929, 37730305, 67084289,
150958081, 268386305, 603906049,
1073643521, 2147483647};
register int k = 0;
while ( gaps[k] < len ) k++ ;
register int i, j, gap;
unsichar_t *__ichar_p = ( unsichar_t * ) a ;
register unsichar_t *tmp = ( unsichar_t * ) malloc( size );
register unsichar_t *prev;
while ( k-- > 0 ) {
gap = gaps[k];
for ( i = gap; i < len; i++ ) {
copy_value_to( __ichar_p + i * size, tmp, size );
//printf("gap=%d, tmp=%d\n", gap, *(int*)tmp);
for ( j = i;
j >= gap && comp( tmp, \
( prev = __ichar_p + ( j - gap ) * size ) ) < 0; j -= gap ) {
copy_value_to( prev, __ichar_p + j * size, size );
}
if ( j < i )
copy_value_to( tmp, __ichar_p + j * size, size );
}
}
//free the heap memory
free( tmp );
}
jsort.h头文件代码在“排序篇 - 插入排序的实现”中可以找到。
Java的实现:
public static final int[] GAPS = new int[] {
1, 5,
19, 41,
109, 209, 505, 929,
2161, 8929,
16001, 36289, 64769,
146305, 260609, 587521, //1000th
1045505, 2354689, 4188161, 9427969,
16764929, 37730305, 67084289,
150958081, 268386305, 603906049,
1073643521, 2147483647};
/**
* shell sort algorithm. <br />
*
* @param arr an array of Comparable items.
*/
public static <T extends Comparable<? super T>> void shellSort( T[] arr ) {
int j, k = 0, gap;
for ( ; GAPS[k] < arr.length; k++ ) ;
while ( k-- > 0 ) {
gap = GAPS[k];
for ( int i = gap; i < arr.length; i++ ) {
T tmp = arr[ i ];
for ( j = i;
j >= gap && tmp.compareTo( arr[ j - gap ] ) < 0; j -= gap ) {
arr[ j ] = arr[ j - gap ];
}
if ( j < i ) arr[ j ] = tmp;
}
}
}
有问题我们一起讨论。