基礎排序
數據結構與算法之基礎排序(冒泡/插入/選擇)<十>
希爾排序
希爾排序又稱爲縮小增量排序。該算法是一個泛化的插入排序,插入排序在序列幾乎有序的情況下非常有效。希爾排序利用此特性,分多路並使用不同的間距進行插入排序,當間距爲1是則就是簡單的插入排序,本質上希爾排序是插入排序的簡單拓展
優點
對中等大小的序列非常有效
是所有已知O(n^2)排序算法中最快的
相對簡單的排序算法
缺點
較大序列不是個好的選擇
不及 歸併 堆 快速排序有效
明顯比 歸併 堆 快速 排序慢
算法
選擇合適的間距 將序列分成n路
每路使用插入排序
重複上述過程直至間距爲1
堆排序
堆排序是一種基於比較的排序算法,該算法同時屬於選擇排序。雖然在大多數計算機上的運行效率低於快速排序。但是堆排序最大的優勢是在最壞情況下O(nlogn)
關於堆的基礎知識參考數據結構與算法之優先隊列<九>
以下算法實現僅供參考若有錯誤歡迎指正
希爾排序
public void sortByShell2(int[] a) {
int d = SIZE;
while (true) {
// 將數組分成d路然後每列進行插入排序
d = d / 2;
// 遍歷所有路 每路進行插入排序
for (int j = d; j < arr.length; j++) {
// 若第i個元素大於i-1元素,該位置元素位置正確。小於的話,後移空出位置
if (a[j] < a[j - d]) {
//下個元素位置
int n = j - d;
// 複製爲哨兵,即存儲待排序元素
int x = a[j];
// 先後移 空出位置
a[j] = a[j - d];
// 循環查找插入位置 直至找到或者到頭
while (n >= d && x < a[n - d]) {
a[n] = a[n - d];
//下個元素位置
n = n - d;
}
// 插入到正確位置
a[n] = x;
}
}
// 步長爲1時便是插入排序了 排序也就完成了
if (d == 1) {
break;
}
}
}
堆排序
// 調整堆父節點小
public void adjustHeap(int[] heap, int node, int length) {
// 保存被調整的節點
int temp = heap[node];
// 利用完全二叉樹的特殊性,父節點與子節點的關係child=father*2+1
int child = node * 2 + 1;
while (child < length) {
// 如果存在右孩子且右孩子小於左孩子
if ((child + 1) < length && heap[child] < heap[child + 1]) {
// 選擇小的孩子
++child;
}
// 如果父節點大於孩子中最小的
if (heap[node] < heap[child]) {
heap[node] = heap[child];
// 向下繼續調整
node = child;
child = node * 2 + 1;
} else {
break;
}
// 調整完畢 找到了正確位置
heap[node] = temp;
}
}
// 建立堆
public void buildHeap(int[] arr, int length) {
// 根據child=node*2+1可以算出數列中最後一個節點
for (int node = (length - 1) / 2; node >= 0; --node) {
// 從下自上將所有的節點調整一遍
adjustHeap(arr, node, length);
}
}
// 將創建好的堆進行堆排序
public void sortByHeap(int[] array, int length) {
buildHeap(array, length);
int temp;
// 將數組遍歷從尾部到頂依次與根節點互換
for (int i = length - 1; i > 0; --i) {
temp = array[i];
array[i] = array[0];
array[0] = temp;
// 將根節點替換後從上向下調整
adjustHeap(array, 0, i);
}
}
到此希爾排序和堆排序介紹完畢