希尔排序
- 时间复杂度:平均O(n^1.3),最好为O(n),最坏为0(n ^ 2)
- 空间复杂度:O(1)
- 稳定性:不稳定
算法解析:
- 希尔排序是直接插入排序的一种改进,又称做缩小增量排序
- 希尔排序是把待排序集合计算出一个增量集合Tn
- 把待排序集合分成若干个子集,然后每个子集进行直接插入排序,知道Ti=1为止,排序结束
- 遍历次数为增量集合的count数
举例
有一个集合如下图所示:
list.png
计算增量:gap = length/3 + 1,自己可以查阅为什么是 除以3(除以3交换的次数最少,时间用的最少)
第一次:gap = 4,把待排序列划分为4个子序列
第一次.png
第二次 :gap = 2,把待排序列划分为2个子序列
第二次.png
第三次:gap = 1,进行一次直接插入排序,排序结束
排序结果:
result.png
动画演示
shellSort.gif
C语言实现
void shellSort(int arr[],int length) {
//增量计算,计算间隔
int gap = length/3 + 1;
while (gap > 0) {
for (int i = gap; i<length; i++) {
int tmp = arr[i];
int j = i-gap;
if (j >= 0 && arr[j] > tmp) {
arr[j+gap] = arr[j];
j-=gap;
}
arr[j+gap] = tmp;
}
if (gap == 1) { break; }
gap = gap/3 + 1;
}
}
OC实现
- (NSArray *)shellSort:(NSMutableArray *)arr {
NSUInteger length = arr.count;
NSInteger gap = length/3 + 1;
while (gap > 0) {
for (NSUInteger i = gap; i < length; i++) {
NSNumber *tmp = arr[i];
NSUInteger j = i-gap;
if (j >= 0 && [arr[j] intValue] > [tmp intValue]) {
arr[j+gap] = arr[j];
j -= gap;
}
arr[j+gap] = tmp;
}
if (gap == 1) {break;}
gap = gap/3 + 1;
}
return arr.copy;
}
Swift实现
func shellSort(arr: inout [Int]) -> Void {
let length = arr.count
var gap = length/3 + 1
while gap > 0 {
for index in 0..<length {
let tmp = arr[index]
var j = index-gap
while j >= 0 && arr[j] > tmp {
arr[j+gap] = arr[j]
j = j - gap
}
arr[j+gap] = tmp
}
if gap == 1 { break }
gap = gap/3 + 1
}
}
以下实现来源于网络,未验证
c++实现
void shell_sort(const int start, const int end) {
int increment = end - start + 1; //初始化划分增量
int temp{ 0 };
do { //每次减小增量,直到increment = 1
increment = increment / 3 + 1;
for (int i = start + increment; i <= end; ++i) { //对每个划分进行直接插入排序
if (numbers[i - increment] > numbers[i]) {
temp = numbers[i];
int j = i - increment;
do { //移动元素并寻找位置
numbers[j + increment] = numbers[j];
j -= increment;
} while (j >= start && numbers[j] > temp);
numbers[j + increment] = temp; //插入元素
}
}
} while (increment > 1);
}
js实现
function shellSort(arr) {
var len = arr.length,
temp,
gap = 1;
while(gap < len/3) { //动态定义间隔序列
gap =gap*3+1;
}
for (gap; gap > 0; gap = Math.floor(gap/3)) {
for (var i = gap; i < len; i++) {
temp = arr[i];
for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) {
arr[j+gap] = arr[j];
}
arr[j+gap] = temp;
}
}
return arr;
}
Python 代码实现
def shellSort(arr):
import math
gap=1
while(gap < len(arr)/3):
gap = gap*3+1
while gap > 0:
for i in range(gap,len(arr)):
temp = arr[i]
j = i-gap
while j >=0 and arr[j] > temp:
arr[j+gap]=arr[j]
j-=gap
arr[j+gap] = temp
gap = math.floor(gap/3)
return arr
}
Go 代码实现
func shellSort(arr []int) []int {
length := len(arr)
gap := 1
for gap < gap/3 {
gap = gap*3 + 1
}
for gap > 0 {
for i := gap; i < length; i++ {
temp := arr[i]
j := i - gap
for j >= 0 && arr[j] > temp {
arr[j+gap] = arr[j]
j -= gap
}
arr[j+gap] = temp
}
gap = gap / 3
}
return arr
}
Java 代码实现
public class ShellSort implements IArraySort {
@Override
public int[] sort(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
int gap = 1;
while (gap < arr.length) {
gap = gap * 3 + 1;
}
while (gap > 0) {
for (int i = gap; i < arr.length; i++) {
int tmp = arr[i];
int j = i - gap;
while (j >= 0 && arr[j] > tmp) {
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = tmp;
}
gap = (int) Math.floor(gap / 3);
}
return arr;
}
}
PHP 代码实现
function shellSort($arr)
{
$len = count($arr);
$temp = 0;
$gap = 1;
while($gap < $len / 3) {
$gap = $gap * 3 + 1;
}
for ($gap; $gap > 0; $gap = floor($gap / 3)) {
for ($i = $gap; $i < $len; $i++) {
$temp = $arr[$i];
for ($j = $i - $gap; $j >= 0 && $arr[$j] > $temp; $j -= $gap) {
$arr[$j+$gap] = $arr[$j];
}
$arr[$j+$gap] = $temp;
}
}
return $arr;
}