一、插入排序
1.1 直接插入排序
基本思想
將一個記錄插入到已排好序的序列中,從而得到一個新的有序序列(將序列的第一個數據看成是一個有序的子序列,然後從第二個記錄逐個向該有序的子序列進行有序的插入,直至整個序列有序)
重點:使用哨兵,用於臨時存儲和判斷數組邊界。
空間複雜度:O(1)。
時間複雜度:O(n^2)。在最好情況下,表中元素已經有序,此時每插入一個元素,都只需要比較一次而不用移動元素,因此時間複雜度爲O(n^2)。
穩定性:每次插入元素時總是從後向前先比較再移動,所以不會出現相同元素相對位置發生變化的情況。即直接插入排序是一個穩定的排序方法。
流程圖
算法實現
public class Sort {
public static void main(String[] args) {
int arr[] = {2,1,5,3,6,4,9,8,7};
int temp;
for (int i=1;i<arr.length;i++){
//待排元素小於有序序列的最後一個元素時,向前插入
if (arr[i]<arr[i-1]){
// 假設某時序列 {4,5,6,7} ,下個待插入元素1
temp = arr[i];
for (int j=i;j>=0;j--){
if (j>0 && arr[j-1]>temp) {
arr[j]=arr[j-1];
}else {
arr[j]=temp;
break;
}
}
}
}
System.out.println(Arrays.toString(arr));
}
}
1.2 希爾排序
直接插入排序存在的問題:
當後面插入的數較小的話,前面排好序的元素後移的次數會明顯的增多,對效率有影響。
希爾排序:
在直接插入排序的基礎上進行改進,也稱爲縮小增量排序。
基本思想:
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減少至1時,整個元素集合被分成一組,算法便終止。
空間複雜度:O(1)。
時間複雜度:當n在某個特定範圍時,希爾排序的時間複雜度約爲O(n^1.3)。在最壞情況下希爾排序排序的時間複雜度爲O(n^2)。
穩定性:當相同關鍵字的記錄被劃分到不同的子表時,可能會改變他們之間的相對次序,因此希爾排序是一個不穩定的排序方法。
動態圖解:
算法實現
import java.util.Scanner;
public class Shell_sort {
//希爾排序是非穩定的排序算法
//基本思想:
//先取一個小於n的整數d1作爲第一個增量,把所有數據分組。所有距離爲d1的倍數的記錄放在同一個分組中。先在各組內進行直接插入排序;
//然後,取第二個增量d2<d1重複上述的分組和排序。直至所取的增量d=1,即所有記錄放在同一組中進行直接插入排序爲止
//一般的初次取序列的一半爲增量,以後每次減半,直到增量爲1
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("請輸入數組的大小:");
Scanner input = new Scanner(System.in);
int a = input.nextInt();
int [] arr = new int[a];
for(int i = 0;i<arr.length;i++) {
System.out.println("請輸入數組的第"+i+"個值:");
int s = input.nextInt();
arr[i] = s;
}
arr = HillSort(arr);
for(int i = 0;i<arr.length;i++)
System.out.print(" "+arr[i]+" ");
}
public static int[] HillSort(int[] arr) {
//單獨將數組的長度拿出來,提高效率
int length = arr.length;
//截取的長度不爲1則一直計算
while(length!=0) {
//取整,相當於每組的元素個數
length = length/2;
//每組有多少個元素,就循環幾次
for(int i =0;i<length;i++) {
int tem = arr[i];
//對元素進行分組
for(int j = i+length;j<arr.length;j+=length) {
//k的值爲每組最後一個數值的數組下標。
int k = j-length;
//將每個要插入進來的數賦給中間變量
int temp = arr[j];
//將這個數進行比較,如果小於已排好序的這個數組,那麼數組的位置就往後移
while(k>=0&&temp<arr[k]) {
//對應元素後移
arr[k+length] = arr[k];
//對應下標前移
k-= length;
}
//找到不小於已排好序的數組中的元素的位置,將其插入
arr[k+length] = temp;
}
}
}
return arr;
}
}