快速排序算法_常用排序算法之快速排序
????點擊上方藍色 “鐵匠學編程” 關注我,讓我們一起學習!
????前天給大家分享了歸并排序,但是它不是原地排序算法,需要消耗額外的內存空間,今天給大家分享的是江湖無人不知無人不曉的"快排"--快速排序。
快排是小生接觸開發學會的第一個排序算法?
快速排序原理
????快排也用到了分治思想。快排的核心思想是:如果要排序的數組中下標從 p 到 r 之間的一組數據,我們選擇 p 到 r 之間的任意一個數據作為分區點 pivot。
????我們遍歷p 到 r 之間的數據,將小于 pivot 的放到左邊,將大于 pivot 的放到右邊,將 pivot?放到中間。經過這一步之后,數組 p 到 r 之間的數據就被分成了三個部分,前面 p 到 q-1 之間都是小于 pivot 的,中間是 pivot ,后面的 q+1 到 r 之間都是大于 pivot 的。
如下圖:
????根據分治、遞歸的處理思想,我們可以用遞歸排序從下標 p 到 q-1 之間的數據和下標從 q+1 到 r 之間的數據,直到區間縮小為1,就說明所有的數據都有序了。快排不需要歸并那樣做合并,也不需要額外的存儲空間,在時間復雜度一樣的情況下有著比歸并更好的空間復雜度表現。
????快排首先找到分區點,一般我們會將數組第一個或最后一個元素作為 pivot,我們以最后一個作為分區點 pivot,然后通過兩個變量 i 和 j 作為下標來循環數組,當下標 j 對應數據小于 pivot 時,交換 i 和 j 對應數據,并且將 i往前移動一位,否則 i 不動,下標 j 始終是往前移動的, j 到達終點后,將 pivot 與下標 i 對應數據交換,這樣最終將 pivot?置于數組中間,[0...i-1]區間的數據都比 pivot 小,[i+1...j] 之間的數據都比 pivot 大,我們以遞歸的方式循環處理,最終整個數組都會變成有序的,如下圖:
????因為分區的過程涉及交換操作,如果數組中有兩個相同的元素,比如序列 7, 9,5,7,3,6 經過第一次分區操作之后,兩個 7的相對先后順序會改變。所以,快速排序并不是一個穩定的排序算法。
代碼示例
Go語言:
package mainimport "fmt"func main() { arr := []int{8, 3, 4, 5, 9, 2, 1} QuickSort(arr) fmt.Println(arr)}func QuickSort(arr []int) { separateSort(arr, 0, len(arr)-1)}func separateSort(arr []int, start, end int) { if start > end { return } i := partition(arr, start, end) separateSort(arr, start, i-1) separateSort(arr, i+1, end)}func partition(arr []int, start, end int) int { pivot := arr[end] var i = start for j := start; j < end; j++ { if arr[j] < pivot { if !(i == j) { arr[i], arr[j] = arr[j], arr[i] } i++ } } arr[i], arr[end] = arr[end], arr[i] return i}PHP示例:
function quick_sort($nums){ if (count($nums) <= 1) { return $nums; } quick_sort_c($nums, 0, count($nums) - 1); return $nums;}function quick_sort_c(&$nums, $p, $r){ if ($p >= $r) { return; } $q = partition($nums, $p, $r); quick_sort_c($nums, $p, $q - 1); quick_sort_c($nums, $q + 1, $r);}// 尋找pivotfunction partition(&$nums, $p, $r){ $pivot = $nums[$r]; $i = $p; for ($j = $p; $j < $r; $j++) { // 原理:將比$pivot小的數丟到[$p...$i-1]中,剩下的[$i..$j]區間都是比$pivot大的 if ($nums[$j] < $pivot) { $temp = $nums[$i]; $nums[$i] = $nums[$j]; $nums[$j] = $temp; $i++; } } // 最后將 $pivot 放到中間,并返回 $i $temp = $nums[$i]; $nums[$i] = $pivot; $nums[$r] = $temp; return $i; } $nums = [4, 5, 6, 3, 2, 1]; $nums = quick_sort($nums); print_r($nums);? JS示例:
const swap = (arr, i, j) => { const temp = arr[i] arr[i] = arr[j] arr[j] = temp}// 獲取 pivot 交換完后的indexconst partition = (arr, pivot, left, right) => { const pivotVal = arr[pivot] let startIndex = left for (let i = left; i < right; i++) { if (arr[i] < pivotVal) { swap(arr, i, startIndex) startIndex++ } } swap(arr, startIndex, pivot) return startIndex}const quickSort = (arr, left, right) => { if (left < right) { let pivot = right let partitionIndex = partition(arr, pivot, left, right) quickSort(arr, left, partitionIndex - 1 < left ? left : partitionIndex - 1) quickSort(arr, partitionIndex + 1 > right ? right : partitionIndex + 1, right) }}性能分析
最后我們看下快速排序的性能和穩定性:
時間復雜度:是O(nlogn),同樣要優于冒泡和插入排序
空間復雜度:不需要額外的空間存放排序的數據,是原地排序
算法穩定性:涉及數據交換,可能破壞原來相等元素的位置排序,所以是不穩定的排序算法
加個關注吧!
加油!不僅自己~還有你~
總結
以上是生活随笔為你收集整理的快速排序算法_常用排序算法之快速排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 课程及其编码字典python_【课程15
- 下一篇: python os模块下载_Python