希尔排序
希尔排序
希尔排序是一种基于插入排序的排序算法,对于大规模乱序数组的排序,插入排序很慢,因为它志辉交换相邻的元素,因此元素只能一点一点地从数组的一端移动到另一端。假设,数组中最小的数正好在数组的尽头,要将它移动到适合的位置就要进行N-1次移动。希尔排序为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。
希尔排序的思想是:先将整个待排序的数组分割成若干个等长的子序列分别进行插入排序,使得若干子数组称为递增序列,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小),再对全体元素进行依次插入排序,因为插入排序在元素基本有序的情况下,效率是最高的。
假设有7个元素的数组,1 10 -5 9 8 7 3,现在要对他们进行希尔排序,图1-1展示了对数组希尔排序的步骤,在排序时,每段等长的数组会进行插入排序,当arr[i]<arr[i-step]时,替换两个位置上的元素,再检查arr[i-step]和arr[i-2*step],如果arr[i-step]<arr[i-2*step],再接着替换两个位置上的元素,以此类推,直到arr[i-n*step]>arr[i-(n+1)*step]
图1-1
由于希尔排序的时间复杂度依赖于递增序列,不同的序列时间复杂度不同,因此希尔排序的时间复杂度分析还是一个待解决的问题。
代码1-2为希尔排序的C语言实现
#include <stdio.h> void shell_sort( int arr[], int len ); void shell_sort( int arr[], int len ) { int step = len; int i = 0, j = 0, temp = 0; while ( 1 ) { step /= 2; for ( i = step; i < len; i++ ) { for ( j = i; j >= step && arr[j] < arr[j - step]; j -= step ) { temp = arr[j]; arr[j] = arr[j - step]; arr[j - step] = temp; } } if ( step == 1 ) { break; } } } void main() { int i = 0; int arr[] = { 1, 10, -5, 9, 8, 7, 3 }; int len = sizeof(arr) / sizeof(arr[0]); printf( "待排序数组:" ); for ( i = 0; i < len; i++ ) { printf( "%d ", arr[i] ); } printf( "\n" ); shell_sort( arr, len ); printf( "排序后数组:" ); for ( i = 0; i < len; i++ ) { printf( "%d ", arr[i] ); } }
代码1-3为希尔排序的Java实现
import java.util.Arrays; public class Shell { public static void shellSort(int... arr) { int step = arr.length; while (true) { step = (int)Math.ceil(step/2); for (int i = step; i < arr.length; i++) { for (int j = i; j >= step && arr[j] < arr[j - step]; j -= step) { int temp = arr[j]; arr[j] = arr[j - step]; arr[j - step] = temp; } } if(step == 1){ break; } } } public static void main(String[] args) { int[] arr = { 1, 10, -5, 9, 8, 7, 3}; System.out.print("待排序数组:" + Arrays.toString(arr)); System.out.println(); shellSort(arr); System.out.println("排序后数组:" + Arrays.toString(arr)); } }
代码1-4为希尔排序的Python实现
# coding:utf-8 def shell_sort(arr): step = len(arr) while True: step /= 2; for i in range(step, len(arr)): j = i while j >= step and arr[j] < arr[j - step]: temp = arr[j] arr[j] = arr[j - step] arr[j - step] = temp j -= step if step == 1: break arr = [1, 10, -5, 9, 8, 7, 3] print "待排序数组:", arr shell_sort(arr) print "排序后数组", arr
代码1-5为希尔排序的Scala实现
import java.util.Arrays object Shell { def shellSort(comparator: (Int, Int) => Boolean)(arr: Array[Int]) { var step = arr.length while (step != 0) { for (i <- step until arr.length) { var j = i while (j >= step && comparator(arr(j - step), arr(j))) { var temp = arr(j) arr(j) = arr(j - step) arr(j - step) = temp j -= step } } step /= 2 } } def main(args: Array[String]): Unit = { val arr = Array(1, 10, -5, 9, 8, 7, 3) println("待排序数组:" + Arrays.toString(arr)) shellSort(_ > _)(arr) println("排序后数组:" + Arrays.toString(arr)) } }