插入排序與希爾排序

插入排序與希爾排序講解

  希爾排序是打破了O(n^2)時間複雜度的排序方法,它的理念基礎是插入排序數組

插入排序概念

  對同一個數組,咱們構思出一個有序數組arr[0],一個無序數組arr[1]開始,無序數組的遍歷就是對有序數組的插入元素的篩選spa

  相比較冒泡和選擇的交換式排序方式,插入排序的替換方式更加簡單,咱們來直接看一下代碼演示排序

插入排序代碼 1.0版

/**
* 插入排序
* 1.咱們能夠看作有兩個數組,分別是有序和無序的
* 有序:arr[0]開始
* 無序:arr[1]開始
* 咱們每次從無序的數據中獲取一個,插入到有序列表中,只須要判斷當 插入的數據 > 有序中的數據就能夠了
* 緣由:有序數據自己就是有序的
* */
public void insertSorting(int[] arr){

int a;
int value = arr[1]; //記錄須要插入的數據
//第一次排序
for(a=0;a>=0;a--){
if(arr[a] < value){
arr[a+1] = value;
break;
}else{
arr[a+1] = arr[a];
}
}
arr[a+1] = value;

//第二次排序
value = arr[2];
for(a=1;a>=0;a--){
if(arr[a] < value){
arr[a+1] = value;
break;
}
arr[a+1] = arr[a];
}
arr[a+1] = value;

//第三次排序
value = arr[3];
for(a=2;a>=0;a--){
if(arr[a] < value){
arr[a+1] = value;
break;
}
arr[a+1] = arr[a];
}
arr[a+1] = value;

//第N次排序
//......
}
總結:根據排序規律能夠看到 無序元素value = 咱們須要插入的元素,來自於arr數組索引1後面的全部
有序元素 a = arr[0],當有無序元素進來時判斷,及時發現value < arr[0],value須要前移也只是進行arr[a+1] = arr[a]的操做,直到找到了value的位置
   咱們才進行了交換

插入排序代碼 2.0版

/**
* 咱們經過查看上述規律,提取最大層的for循環控制須要插入的數arr[b] b = 1開始
* */
public void insertSorting_2(int[] arr){
int a;
for(int b=1;b<arr.length;b++){
int value = arr[b];
for(a=b-1;a>=0;a--){
if(arr[a] < value){
break;
}
arr[a+1] = arr[a];
}
arr[a+1] = value;
}
}

插入排序代碼 3.0版

/**
* 插入排序繼續改進
* 咱們繼續對以上進行改進
* a=b-1(表明了咱們須要判斷的全部索引),a>=0,arr[a] < value 兩個判斷依據進行提取
* */
public void insertSorting_3(final int[] arr){
for(int b=1;b<arr.length;b++){
int value = arr[b];
int a = b-1;
while(a>=0 && arr[a] > value){
arr[a+1] = arr[a];
a--;
}
arr[a+1] = value;
}
}

希爾排序概念

  希爾排序的理念基礎依舊是插入排序,插入排序若是你吃透了的話看希爾排序會很是的簡單,你只須要了解一個思想 --- 步值索引

希爾排序代碼(不完整)和插入排序比較

  咱們引入咱們以前的插入排序2.0版本的代碼來作個比較for循環

/**
* 希爾排序
* 有別於插入排序,他進行拆分比較,並經過步長來進行比較
* */
public void xrSorting(int[] arr){
int c = 1;
for(int b=c;b<arr.length;b++){
int value = arr[b];
int a;
for(a=b-c;a>=0;a--){
if(arr[a] < value){
break;
}
arr[a+1] = arr[a];
}
arr[a+1] = value;
}
}
/**
* 插入排序2.0版本,和上述的希爾排序進行對比
* */
public void insertSorting_2(int[] arr){
int a;
for(int b=1;b<arr.length;b++){
int value = arr[b];
for(a=b-1;a>=0;a--){
if(arr[a] < value){
break;
}
arr[a+1] = arr[a];
}
arr[a+1] = value;
}
}
區別:咱們對比希爾和插入的代碼發現,這個希爾是否是寫錯了?這不是和插入同樣的嗎?非也,int c是他們的關鍵區別,也不能說區別,是插入排序的最終變化
   當c = 1的時候看起來和插入徹底一致是由於插入的無序arr[1]開始其實就是定義了 c = 1,c能夠稱之爲步長,咱們可讓c = 2,3,4,5等等
例1:[2, 3, 5, 7, 9, 1, 2, 3, 5, 0],咱們讓C = arr.length/2 = 5,其實就是拆成了[2,1][3,2][5,3][7,5][9,0]五組分別進行插入
輸出答案[1, 2, 3, 5, 0, 2, 3, 5, 7, 9]拆成的五組分別爲[1,2][2,3][3,5][5,7][0,9]
接下來的思路,咱們繼續 c/2 = 2組,步長C = 2,直至C=1,最後作的一次傳統的插入排序
例1:
/**

* 希爾排序
* 有別於插入排序,他進行拆分比較,並經過步長來進行比較
* */
public void xrSorting(int[] arr){
int c = arr.length/2; //這裏c = 5
for(int b=c;b<arr.length;b++){
int value = arr[b];
int a;
for(a=b-c;a>=0;a-=5){
if(arr[a] < value){
break;
}
arr[a+5] = arr[a];
}
arr[a+5] = value;
}
}

希爾排序代碼 1.0版

/**
* 希爾排序1.0
* 經過最外層的for循環控制c的變化
* */
public void xrSorting(int[] arr){
for(c = arr.length/2;c>=1;c/=2){
for(int b=c;b<arr.length;b++){
int value = arr[b];
int a;
for(a=b-c;a>=0;a-=c){
if(arr[a] < value){
break;
}
arr[a+c] = arr[a];
}
arr[a+c] = value;
}
}
}

希爾排序代碼 2.0版

/** * 希爾排序2.0 * 和插入排序改進相似,咱們提取其中代碼進行代碼整合 * */public void xrSorting_2(int[] arr){    int c;    for(c = arr.length/2;c>=1;c/=2){        for(int b=c;b<arr.length;b++){            int value = arr[b];            int a = b-c;            while(a >= 0 && arr[a] > value){                arr[a+c] = arr[a];                a-=c;            }            arr[a+c] = value;        }    }}若是咱們的c = arr.length / arr.length的話其實本質就是一個原始的插入排序,可是通常狀況下咱們的時間複雜度要小於O(n^2),對於C的選擇要合理
相關文章
相關標籤/搜索