今天集中把幾種排序的方法列一下,當然最出名的希爾,快排,歸併和其優化當然也是滿載
說到希爾排序的話,不得不先提到的就是插入排序了,希爾排序就是對直接插入排序的一種優化,下面就是直接插入排序的思想
直接插入排序
這就是直接插入排序的**,思想很簡單,**也很簡單
為什麼希爾排序比直接插入排序更加優化呢?當需要排序的陣列過長的時候,有可能出現,插入資料的時候需要把資料插入到陣列頭的位置,那麼陣列中需要移動的資料就太多了,效率很低,但是當陣列趨於有序的時候,直接插入排序的效率是很高的,所以希爾排序可以理解為直接插入排序的預排序,讓陣列更趨於有序,希爾排序的最後一趟排序就是直接插入排序
希爾排序
將乙個陣列進行分組(就是隔幾個元素分為一組)如下圖
分組之後,對每一組都進行插入排序,執行完一次所有的分組的插入排序之後算作完成一趟排序,然後減少gap的值,直到最後一次gap的值會變為1,成為直接插入排序
下面是**
void shellsort(int *a,size_t size)
a[end + gap] = tmp;}}
}
每次對gap的值進行gap=gap/3+1,為啥?因為比較優,具體應該就是數學問題了,我就不太清楚了。。。。
接下來是選擇排序,選擇選擇,就是每一次選出最大(小)值,然後交換到最高(低)的位置,優化!一次不僅可以選出最小的值,還可以選出最大的,同時選出,同時交換,可以提高效率
void selectsort(int *a,size_t size )
if ( a[max]< a[j])
}swap(a[i], a[min]);
swap(a[size - 1 - i], a[max]);}}
思想啥的就不貼了,畢竟是比較簡單和基礎的排序了
堆排序
接下來就是堆排序了!什麼是堆,這裡我就進行簡單的介紹了,堆的本質是乙個陣列,將這個陣列看成乙個二叉樹,很抽象,來個圖
順序把陣列弄成二叉樹,大堆(每個父親節點都比孩子節點的值要大),小堆(每個父親節點都比孩子節點的值要小,上圖就是乙個小堆),所謂的堆排序就是把待排序的陣列先建堆
每一次交換之後將調整的範圍縮小乙個,這樣就能保證,每次交換到最後的數都是大數,並到了自己應該到的位置上去,建堆的過程用到向下調整,,每一次交換之後也要向下調整,堆是一種資料結構,這裡就不詳解了,之後會整理出堆來,這裡介紹堆排序的思想和**
void adjustdown(int *a, size_t size, int root)
if (a[child]>a[root])
else
}}void heapsort(int *a, size_t size)
for (int i = size - 1; i >= 0; --i)
}
接下來就是快排了!!這個被譽為十大演算法的傢伙!!
快速排序
快排的思想是拆分遞迴,直到遞迴到最深層(就乙個元素)
但是不夠優化,當每次取的key值恰好比較接近最大值或者最小值的時候,分界遞迴的時候就會出現分布不均勻,導致效率低下,當劃分成兩邊相等的時候自然比較好,所以加上這個部分會比較好
int getmidindex(int *a, int left, int right)
else if (a[mid] < a[right])
else
return right;
}else
else if (a[mid] < a[left])
else
return left;}}
三數取中法,**已經更新過了,所以上邊的快排已經是用三數取中優化過的
當快排遞迴到比較深層的時候,被分成小部分的區間內已經趨於有序了,那麼採用直接插入排序就可以有效的提高效率!!具體做法就是在quicksort中的if部分修改,改掉遞迴結束條件,然後加上直接插入排序的**就好了
這個不能算是優化,思想有些不同,這次是從同一邊走採用cur和prev兩個引數,外層的遞迴還是不變的,只是一次排序不同了
最後key值還是會跑到大概中間的位置,和他自己應該在的地方比較接近
最後乙個排序就是歸併排序啦!
歸併排序
歸併排序一上來就將陣列分割成兩部分,然後不停的分割,直到乙個元素不能再分位置,然後開始合併相鄰的兩個元素,合併之後當然是有序的,有序之後就可以回到上一層,然後不斷的進行合併,最後整個陣列都有序啦,也就是說要想合併,兩個部分都必須是有序的才行。
就是類似這樣的
思想還是不太難理解的
實現這樣的思想需要開闢輔助空間,因為當兩部分有序的陣列合併之後還要是有序的才行,需要乙個同等大小的陣列暫存一下資料
void mergeselection(int *a, int *tmp, int begin1, int end1, int begin2, int end2)
else
tmp[index++] = a[begin2++];
}while (begin1 <= end1)
while (begin2 <= end2)
}void mergesort(int *a ,int *tmp,int left,int right)
}
tmp是我在測試用例中就開闢好的陣列空間,直接作為引數傳進去 常用排序演算法 希爾,歸併,快排
public static comparable void shellsort t arr while h 1 h h 3 public class 歸併排序 對兩個有序序列進行合併 param arr param low param mid param high param temp privat...
排序演算法 快排,歸併
從陣列中隨機選乙個數,比這個數大的放右邊,比這個數小的放左邊。快排中的乙個細節 如果乙個數等於p的時候,既可以在左邊又可以在右邊。這麼做是為了避免如果陣列中所有的數都一樣,則會造成資料的不平衡。快排的目的是能夠使得左邊和右邊的數都差不多,這樣的話時間複雜度就不會退化到o n 2 而是o n logn...
排序演算法 歸併 快排
歸併排序的思想是分治法,如果想要將乙個陣列排序,那麼將這個陣列分為左區間和右區間,左區間一定是小於右區間的,再將左區間繼續劃分,右區間也繼續劃分。最後將排好序的陣列全都歸併起來,這樣聽起來像是從上向下劃分,其實歸併排序主要是是從下向上,合併的過程。先將單個元素的陣列歸併為兩個元素的有序陣列 再將包含...