學習筆記----快速排序的java實現及其改良
快速排序演算法是我們學習資料結構必學的演算法之一,雖然在java中,對列表的排序可直接使用Collections.sort(List l) (這使用的是歸併排序演算法) ,對基本型別的陣列也有Arrays.sort()(這使用的是改進的快速排序演算法),但實現一個快速排序,仍能給自己很多啟發。
很多演算法書上都使用c或者c++實現快排演算法,但是作為一個寫慣了java的程式設計師,再去寫c或c++有著各種水土不服(沒有豐富的API庫幫忙),加上jvm虛擬機器效能的提高,也就可以用java回顧一下以前的快速排序演算法,也算為面試做個準備。 快速排序的平均時間複雜度能達到O(n*log n),最壞情況下 (元素基本有序,中軸選擇總是最大或最小 、元素,此時快速排序退化成氣泡排序)為O(n^2)。
本例中使用隨機選擇中軸元素的方式降低了最壞情況可能性,並在子陣列比較小(在書上推薦是5-15個元素即比較小)的時候停止快排,採用插入排序(最好情況既元素基本有序下,時間複雜度為O(n))完成整個List的排序。 有關快速排序的原理,演算法書上已經講的很清楚了,按照我個人的理解,快速排序就是如何將整個陣列通過選擇的中軸(key)劃分成兩個子陣列,並且滿足(key)這種關係。這就算完成一趟快排了,剩下的只需要遞迴(key)即可。 快排程式碼如下:
public class QuickSort {
static List<Integer> list = new ArrayList<>();
private static int END_QUICKSORT = 7;
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 0; i < 100000; i++) {
list.add((int) (Math.random() * 1000));
//list.add(i);
}
long a1 = System.nanoTime();
quickSort(list);
long a2 = System.nanoTime();
System.out.println(a2 - a1);
/*for (Integer temp : list) {
System.out.println(temp);
}*/
}
public static void quickSort(List<Integer> list) {
quick(list, 0, list.size() - 1);
// 對快排後基本有序陣列進行一次插入排序
insertSort(list);
}
private static void insertSort(List<Integer> list2) {
// TODO Auto-generated method stub
for (int i = 1; i < list2.size(); i++) {
int v = list2.get(i);
int j = i - 1;
for (; j >= 0 && list2.get(j) > v; j--) {
list2.set(j + 1, list.get(j));
}
list.set(j + 1, v);
}
}
private static void quick(List<Integer> list, int low, int hight) {
// TODO Auto-generated method stub
if (low < hight) {
int key = partition(list, low, hight); // 選擇中軸並對子陣列部分排序
if (key - low > END_QUICKSORT)
quick(list, low, key - 1); // 對左半部分繼續使用快排
if (hight - key > END_QUICKSORT)
quick(list, key + 1, hight); // 當(key,hight)範圍小到一定程度,不再進行快排
}
}
private static int partition(List<Integer> list, int low, int hight) {
// TODO Auto-generated method stub
int rand = (int) (Math.random() * (hight - low)) + low;
int key = list.get(rand);
if (rand != low) {
int temp = list.get(low);
list.set(low, key);
list.set(rand, temp);
}
while (low < hight) {
while (low < hight && list.get(hight) >= key)
hight--;
list.set(low, list.get(hight));
while (low < hight && list.get(low) <= key)
low++;
list.set(hight, list.get(low));
}
list.set(low, key);
return low;
}
}
然而比較下原快速排序和隨機化快排的程式碼執行速度發現兩者差別並不大,當然在電腦上還存在其它程式影響執行,不夠準確,所以這個時間值就不貼出來了。
在JDK中,對快速排序做了如下三個優化,有興趣的同學可以去看看Arrays.sort方法的原始碼。
1、就像上面提到的,對於元素數小於7(java內定值)的陣列,直接返回插入排序的結果(因為插入排序對基本有序陣列和簡單陣列能保證線性效能,所以一些O(n^2)的演算法不一定就不能使用)
2、使用三平均劃分法(陣列最左邊,最右邊,最中間的元素的中位數)找到中軸。
3、對於這一點我還不太理解,即是說:將和中軸相等的元素都放到陣列中間,如:4,3,1,15,15,15,23,34,21 . 這樣只需排序(4,3,1)和(23,34,21)這三個子陣列,對於重複元素多的陣列可減少問題規模。
相關文章
- 快速排序 java實現排序Java
- java實現快速排序Java排序
- 快速排序(java實現)排序Java
- 設計模式學習筆記(二十)狀態模式及其實現設計模式筆記
- 【筆記】堆及其實現筆記
- 【筆記】快速排序筆記排序
- 設計模式學習筆記(十八)備忘錄模式及其實現設計模式筆記
- 經典排序演算法及其 Java 實現排序演算法Java
- 學習筆記--- 比較排序之堆排序筆記排序
- 快速排序的實現排序
- 設計模式學習筆記(二十一)訪問者模式及其實現設計模式筆記
- 設計模式學習筆記(二十二)直譯器模式及其實現設計模式筆記
- JAVA學習筆記Java筆記
- 重新學習JAVA的筆記Java筆記
- 《JAVA學習指南》學習筆記Java筆記
- 隨機快速排序Java程式碼實現隨機排序Java
- 快速排序及其優化排序優化
- 排序演算法-Java實現快速排序演算法排序演算法Java
- 學習java筆記 --- 一個實現Iterable介面的小范例Java筆記
- java 學習筆記--利用反射實現自定義toString()的工具類Java筆記反射
- 快速傅立葉變換 學習筆記筆記
- Java 集合學習筆記Java筆記
- java學習筆記6Java筆記
- Java學習筆記--反射Java筆記反射
- java學習筆記啊Java筆記
- Java學習筆記二Java筆記
- Java學習筆記三Java筆記
- Java JNI 學習筆記Java筆記
- Java學習筆記4Java筆記
- Java複習筆記第二篇--集合學習之實現原理二Java筆記
- GO 實現快速排序Go排序
- Swift實現快速排序Swift排序
- Java學習筆記--sql與javaJava筆記SQL
- 通過leetcode學習常見排序演算法及其Go實現LeetCode排序演算法Go
- 【Go學習筆記13】介面和實現Go筆記
- Java學習筆記記錄(二)Java筆記
- Python實現的快速排序Python排序
- 快速排序(Quicksort)的Javascript實現排序UIJavaScript