大话数据结构系列之快速排序算法
大話數(shù)據(jù)結(jié)構(gòu)系列之快速排序算法
文章目錄
- 實現(xiàn)思路
- 重點知識
- 代碼實現(xiàn)
- 優(yōu)化策略
- 算法比較
- 與各位共勉
實現(xiàn)思路
1、屬于冒泡排序的升級版,都是通過不斷的比較和移動交換來實現(xiàn)排序,它的實現(xiàn),增大了記錄的比較和移動的距離,將關(guān)鍵字較大的記錄從前面直接移動到后面,關(guān)鍵字較小的記錄從后面直接移動到前面,從而減少了總的比較次數(shù)和移動交換次數(shù)。
2、通過一趟排序?qū)⒋涗浄指畛瑟毩⒌膬刹糠?#xff0c;其中一部分記錄的關(guān)鍵字均比另一部分記錄的關(guān)鍵字小,則可分別對這兩部分記錄繼續(xù)進行排序,以達到整個序列有序的目的。
重點知識
樞軸:
樞軸左邊的值都比它小,右邊的值都比它大
Partition 函數(shù)(用來尋找樞軸,進行表劃分):
其實就是將選取的 pivotkey 不斷交換,將比它小的換到它的左邊,比它大的換到它的右邊,它也在交換中不斷更改自己的位置,直到完全滿足這個要求為止。
如果每次 pivotkey 選擇的值都最優(yōu),那么遞歸的深度就越淺,那么時間性能就越好
復(fù)雜度分析:
空間復(fù)雜度為O[nlogn]——O[n]
時間復(fù)雜度為 O[nlogn] —— O[n2]
快速排序法的時間復(fù)雜度推導(dǎo)過程:
使用數(shù)學(xué)歸納法進行推導(dǎo):https://blog.csdn.net/weixin_39966065/article/details/104157850
代碼實現(xiàn)
package com.example.sort; import java.util.Arrays; public class QuickSortTest {public static void main(String[] args){//基礎(chǔ)數(shù)據(jù)int[] sortList2 = {0,1,4,3,10,9,6,7,8,5,2,20,18,16,11,13,15,14,17,19,12};System.out.println(Arrays.toString(sortList2));quickSort(sortList2);System.out.println(Arrays.toString(sortList2));}public static void quickSort(int[] list){qSort(list,0,list.length-1);}public static void qSort(int[] list, int low, int high){int pivot;if(low < high){pivot = partition(list,low,high);//分別對高低子表進行排序qSort(list,low,pivot-1);qSort(list,pivot+1,high);}}//采用尾遞歸:將遞歸轉(zhuǎn)換為迭代問題public static void qSort2(int[] list, int low, int high){int pivot;while(low < high){pivot = partition(list,low,high);//分別對高低子表進行排序qSort2(list,low,pivot-1);low = pivot + 1;}}public static int partition(int[] list, int low, int high){int pivotkey;pivotkey = list[low];while(low < high){while( low < high && list[high] >= pivotkey)high--;swap(list,low,high);while( low < high && list[low] <= pivotkey)low++;swap(list,low,high);}return low;}public static int partition1(int[] list, int low, int high){int pivotkey;//優(yōu)化獲取樞軸 //1//三數(shù)取中法:至多增加了3次比較和3次交換指令,而實現(xiàn)了樞軸選取的合理性int m = low + (high - low)/2;if(list[low] > list[high])swap(list,low,high);if(list[m] > list[high])swap(list,high,m);if(list[m] > list[low])swap(list,m,low);pivotkey = list[low];//優(yōu)化不必要的交換操作 //2//將樞軸值備份到 0 的位置list[0] = pivotkey;while(low < high){while( low < high && list[high] >= pivotkey)high--;list[low] = list[high];//swap(list,low,high);while( low < high && list[low] <= pivotkey)low++;list[high] = list[low];//swap(list,low,high);}list[low] = list[0];return low;}public static void swap(int[] list, int i, int j){int temp = list[i];list[i] = list[j];list[j] = temp;} }優(yōu)化策略
1、優(yōu)化選取樞軸
// 默認代碼中: pivotkey = list[low]; 并不適用于所有的情景(當所有值都倒序或者正序時,獲取的值沒有太大意義)
隨機選擇樞抽的方式更適用于大多數(shù)情況,使得獲取的樞軸更合理
三數(shù)取中法(median-of-three)
取三個關(guān)鍵字先進行排序,將中間數(shù)作為樞軸,一般是取左端、右端和中間三個數(shù)。
2、優(yōu)化不必要的交換
3、優(yōu)化小數(shù)組時的排序方案
當 high - low 不大于某個常數(shù)時,就可以直接用插入排序(在小數(shù)組排序中,性能最好),這樣就能保證最大化地利用兩種排序的優(yōu)勢來完成工作。
4、使用尾遞歸方式減少遞歸層數(shù)
算法比較
1、從最好情況看:
如果你的待排序序列總是基本有序,冒泡排序和直接插入排序更勝一籌。時間復(fù)雜度都接近 O[n]
2、從最壞情況看:
堆排序和歸并排序強過快速排序以及其它簡單排序。
3、從平均情況,最好情況,最壞情況,空間復(fù)雜度,穩(wěn)定性來比較
4、從移動次數(shù)來比較三種簡單排序
結(jié)論 :如果記錄的關(guān)鍵字本身信息量比較大(例如:關(guān)鍵字都是數(shù)十位的數(shù)字),此時表明其占用存儲空間很大,這樣移動記錄所花費的時間也越多。
5、為什么綜合各項指標來說,經(jīng)過優(yōu)化的快速排序是性能最好的排序算法?
(1)從最壞情況來看,歸并排序比快速排序好
(2)從最好情況看,兩者相當 ?
快速排序:
最好:nlogn | 最壞:n(n-1)/2
(3)從穩(wěn)定性看,歸并排序具有穩(wěn)定性
(4)從輔助空間上看,歸并排序比快速排序略次(空間一般都不是問題)
(5)從內(nèi)存占用上看,無遞歸的歸并排序比快速排序有優(yōu)勢
待自我論證,使用合適的數(shù)據(jù)規(guī)模
參考文章:https://blog.csdn.net/qq_36770641/article/details/82669788
與各位共勉
數(shù)據(jù)結(jié)構(gòu)和算法對于程序員的人生來說,那就是兩個圓圈的交集部分,用心去掌握它,你的編程之路將會是坦途。
—— 程杰
You got a dream, you gotta protect it. People can’t do something themselves, they wanna tell you can’t do it. If you want something, go get it, Period.
《當幸福來敲門》
總結(jié)
以上是生活随笔為你收集整理的大话数据结构系列之快速排序算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐C语言编译器(手机APP)
- 下一篇: 机械设计基础类毕业论文文献都有哪些?