ds排序--希尔排序_图解直接插入排序和希尔排序
前言
這次我們介紹插入類排序中的 直接插入排序 和 希爾排序 。
對于直接插入排序,雖然它的時間復(fù)雜度也是 O(n^2) ,但是在元素 有序或近乎有序 的情況下,時間復(fù)雜度可以降為 O(n) ,效率比 O(nlogn) 的算法還要高。
然而對于大規(guī)模的亂序數(shù)組,使用直接插入排序的效率是非常低的。此時我們需要使用希爾排序,希爾排序在直接插入排序的基礎(chǔ)上,彌補(bǔ)了直接插入排序只能比較相鄰元素的不足,使得可以按照指定步長比較元素,充分發(fā)揮了直接插入排序?qū)τ谛∫?guī)模有序數(shù)組排序的優(yōu)勢。
下面我們分別介紹 直接插入排序 和 希爾排序 兩類插入排序。
直接插入排序
有如下數(shù)組,我們需要對它從小到大排序,利用直接插入排序步驟如下:
下圖展示了整個排序的過程:
直接插入排序的代碼:
public static void sort(Comparable[] arr) { int n = arr.length; // 0位置不需要比,從1到最后一個位置n-1 for (int i = 1; i <= n - 1; i++) { for( int j = i; j > 0 && arr[j].compareTo(arr[j-1]) < 0 ; j--) { swap(arr, j, j-1); } }}private static void swap(Object[] arr, int i, int j) { Object t = arr[i]; arr[i] = arr[j]; arr[j] = t;}優(yōu)化
優(yōu)化的思路就是將內(nèi)循環(huán)中每次 swap 交換操作修改為 讓較大的元素后移,最后再進(jìn)行一次交換 ,這樣一來訪問數(shù)組的次數(shù)就減少了(交換需要三行,賦值只需要一行)。
優(yōu)化步驟如下:
下圖展示了優(yōu)化思路的過程:
優(yōu)化的直接插入排序代碼:
public static void sort(Comparable[] arr) { int n = arr.length; // 0位置不需要比,從1到最后一個位置n-1 for (int i = 1; i <= n - 1; i++) { // 保存當(dāng)前插入的元素 Comparable e = arr[i]; int j; for (j = i; j > 0 && arr[j - 1].compareTo(e) > 0; j--) { arr[j] = arr[j - 1]; } arr[j] = e; }}希爾排序
上面我們介紹了直接插入排序,它對于大規(guī)模亂序數(shù)組的排序效率比較低,因為只能交換相鄰的元素,所以元素只能一點一點地從數(shù)組的一端移動到另一端。此外,如果最小的元素在數(shù)組的末尾,那么將它插入到正確位置需要移動 N-1 次。
希爾排序的出現(xiàn),解決了上述問題。它能夠交換不相鄰的元素以對數(shù)組的局部進(jìn)行排序,并最終用直接插入排序?qū)⒕植坑行虻臄?shù)組排序。
希爾排序的思想是使數(shù)組中任意間隔為 h 的元素都是有序的。這樣的數(shù)組也叫作 h 有序數(shù)組 。我們不研究 h 是如何得來的,這里直接使用了《算法》書中的 h 步長序列。
h = 3*h+1 ,根據(jù) h 的取值分別為1、4、13 ...
實際上只需要把直接插入排序代碼中移動元素的距離由 1 改為 h 即可。這樣,希爾排序就轉(zhuǎn)換為了一個類似于直接插入排序但使用不同增量的過程。
下圖展示了希爾排序的過程:
如果你仔細(xì)觀察,會發(fā)現(xiàn)在 h=1 時,相比直接插入排序,比較的次數(shù)大大減少了,這是因為希爾排序使得部分子數(shù)組有序,而直接插入排序?qū)τ诮跤行虻臄?shù)組,效率是非常高的。
希爾排序代碼:
public static void sort(Comparable[] arr) { int n = arr.length; // 步長序列: 1, 4, 13... int h = 1; while (h < n / 3) { h = 3 * h + 1; } while (h >= 1) { for (int i = h; i < n; i++) { // 將 arr[i] 插入到 arr[i-h], arr[i-2*h], arr[i-3*h]... 中 Comparable e = arr[i]; int j; // 優(yōu)化的插入排序 for (j = i; j >= h && e.compareTo(arr[j - h]) < 0; j -= h) { arr[j] = arr[j - h]; } arr[j] = e; } h /= 3; }}總結(jié)
以上是生活随笔為你收集整理的ds排序--希尔排序_图解直接插入排序和希尔排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 东京大学团队开发出遇热变身立体模型的折叠
- 下一篇: tomcat8日志乱码_Tomcat输出