各路排序神仙理解以及Java實現
啊啊啊啊啊啊!大話資料結構終於看到了排序這一章章啦,然而各路排序神仙,真的是看懂了!僅僅是看懂了,所以打算用兩天的時間比幾個常見的演算法寫一遍啦,加深一下印象。嚶嚶嚶
氣泡排序
這個演算法我記得是上C語言就接觸了,他的思想是,遇到逆序對,就進行交換啊,就這樣慢慢的第n個有序,第n-1個有序.......全部有序。 關鍵點在於如果一次遍歷,都沒有交換操作的話,那說明已經有序啦,跳出迴圈。排序完成。
package com.it592.sort; public class BubbleSort extends Sort { @Override public void sort(int nums[]) { int len = nums.length; for (int i = 0; i < len; i++){ boolean flag = true; for (int j = 0; j < len - i -1; j++){ if(nums[j] > nums[j+1]){ // 判斷是否逆序,如果逆序,說明還沒找到正確的位置,繼續後移 nums[j] += nums[j+1]; nums[j+1] = nums[j] - nums[j+1]; nums[j] -= nums[j+1]; flag = false; } } if (flag) break; } } }
選擇排序
選擇排序,按照大話資料結構的話說,其實和氣泡排序差不多,但是這兩個演算法的側重點不同,氣泡排序每次都進行交換操作,其實有很多交換是沒有必要的,畢竟交換也要費點時,選擇排序他只是觀察,找到適合某個位置的點,然後再進行交換,這就好比炒股票,氣泡排序是看到每次漲了之後,都賣出去,然後降了再買點回來,而選擇排序是看到最高點,再拋售,這就省去了中間交易的開銷,也就是氣泡排序時候交換的時候開銷。
package com.it592.sort; public class SelectSort extends Sort { @Override public void sort(int[] nums) { for (int i = 0; i < nums.length - 1; i++){ int key = i; for (int j = i + 1; j < nums.length; j++){ //找到適合i的值。 if (nums[key] > nums[j]) key = j; } if(key != i){ nums[i] += nums[key]; //讓i變為有序的 nums[key] = nums[i] - nums[key]; nums[i] -= nums[key]; } } } }
插入排序
插入排序的思想是,假設序列已經有序了,那麼我們只需要把當前元素插入到正確的位置即可。首先,對於第一個元素,因為只有一個元素,所以他是有序的,對於第二個元素,則與第一個元素進行判斷,如果比第一個元素小,則插到第一個元素之前,第一個元素後移;對於第三個元素,則和前兩個元素進行比較,找到合適的位置,插入即可。依次類推,最終有序。
package com.it592.sort; public class InsertSort extends Sort { @Override public void sort(int[] nums) { int len = nums.length; for(int i = 0; i < len -1 ; i++){ int tmp = nums[i+1]; int j = i+1; for(; j > 0; j--){ if(nums[j-1] > tmp){ nums[j] = nums[j-1]; }else break; } nums[j] = tmp; } } }
希爾排序
在插入排序中,由於要把某個元素放到合適的位置上,這樣可能就會導致其他元素偏離他本來的位置很遠,希爾排序是對插入排序的一種改進,他可以將小的元素放到前面去,而大的元素集中在尾部。方法是,將陣列進行分組,例如[2,5,1,4,5,55,11,1,15,19,2,33,55,8],我們設定space=3,那麼則[2,11,19,55],[5,5,1,2,8],[1,55,15,33]為三個分組,使用插入排序對他們進行排序後,就會得到以下結果[2,1,1,11,2,15,19,5,33,55,5,55,8],通過這樣一輪排序之後,就會發現小的部分相對集中在前面,而大數則集中在後面。最終迴圈完畢,有序
package com.it592.sort;
public class ShellSort extends Sort {
@Override
public void sort(int[] nums) {
int gap = nums.length / 3 + 1;
while (true){
for (int i = 0; i < nums.length - gap; i += gap){
int tmp = nums[i+gap];
int j = i + gap;
for (; j > 0; j -= gap){
if(nums[j-gap] > tmp)
nums[j] = nums[j-gap];
else
break;
}
nums[j] = tmp;
}
if (gap == 1)
break;
gap = gap / 3 + 1;
}
}
}