在此我們使用遞迴的快速排序。既然使用了遞迴,自然就是要解決一些重複的子任務,然後完成最後的大任務,而大任務自然就是讓整個陣列整體有序,那需要重複的小任務是什麼呢?
快排的乙個個子任務,就是要在各自範圍內的陣列中取乙個數當基準數(一般取範圍內的最左邊、最右邊或中間的數),然後讓其它的數小於基準數的放左邊,大於基準數的放右邊,這就是快速排序遞迴的子任務。
整體的實現則是先對【1,n】範圍內的數開始任務,任務完成後,基準數已經在中間,再對【1, 基準數的位置-1】和【 基準數的位置+1,n】開始任務,也就是對基準數左邊的範圍和右邊的範圍開始任務,而開始任務其實就是進入下乙個遞迴了。最後所有的遞迴完成後,也就說明所有範圍內的數都已經實現了左邊的數小於當前範圍的基準數,而右邊的數也已經全部大於當前範圍的基準數,自然陣列整體已經是有序的了。不太理解為什麼,可以自己畫一下圖,每次就取最左邊的數作為基準數。
首先我們取範圍內最左邊的數做為基準數,然後讓i
、j
分別指向最左邊和最右邊的位置,再是開始迴圈。迴圈的條件需要是i < j
,然後因為我們取的是最左邊的數,所以我們需要從右邊開始向左查詢比基準數要小的數,至於為什麼取最左邊就要從右邊開始查詢,這是為了之後基準數歸位時,i
所指向位置的數必定是小於基準數的,這樣讓基準數跟i
所在位置的數進行交換,不會影響任務的完成。查詢到比基準數小的數之後停止迴圈,再開始從左邊往右開始查詢比基準數大的數,查到之後停止迴圈。然後交換兩個查詢到的數,即把比基準數大的數放到右邊,比基準數小的數放在左邊,再是開始下個查詢,直到i >= j
。如果期間遇到查詢不到的情況,完全沒有問題,因為你會發現,最終i
指向的值必定小於基準數,而i
下乙個位置的數要麼沒有數,要麼就是比基準數大的數,最後把基準數和i
所指向的數進行交換,任務就完成了。接著就開始基準數左邊和右邊的子任務,任務流程是一樣的。
class
solution
~solution()
void
quicksort
(vector<
int>
& nums,
int left,
int right)
int tmp = nums[left]
;int i = left, j = right;
while
(i < j)
while
(i < j && nums[i]
<= tmp)
if(i < j)
} nums[left]
= nums[i]
; nums[i]
= tmp;
quicksort
(nums, left, i -1)
;quicksort
(nums, i +
1, right);}
vector<
int>
sortarray
(vector<
int>
& nums)
};
平均情況
最好情況
最壞情況
o (n
log2
n)
o(nlog)
o(nlog
2n)
o (n
log2
n)
o(nlog)
o(nlog
2n)
o (n
2)
o(n^2)
o(n2
)輔助儲存
o (n
log2
n)
o(nlog)
o(nlog
2n)
不穩定,快速排序在排序的時候,會把相同關鍵字的順序打亂,就是本來在前面出現的數可能會被放到後面。
排序演算法 快速排序演算法
網際網路的大型公司還在火熱招聘中,參與了一次又一次的筆試,都不通過,我還是太菜!作為程式設計人員,需要邁過去 資料結構與演算法 這個坎,畢竟,筆試不會真的很虧,加油吧,少些水,多點實操。一 快速排序演算法思想 從一組資料中找出乙個基準值,一般是選擇中間值作為基準值,然後從左到右將值與基準值進行比較,...
演算法 排序演算法 快速排序
快速排序是對冒泡法排序的一種改進。快速排序演算法 的基本思想是 將所要進行排序的數分為左右兩個部分,其中一部分的所有資料都比另外一 部分的資料小,然後將所分得的兩部分資料進行同樣的劃分,重複執行以上的劃分操作,直 到所有要進行排序的資料變為有序為止。可能僅根據基本思想對快速排序的認識並不深,接下來以...
排序演算法 快速排序
快速排序使用分治法 divide and conquer 策略來把乙個序列 list 分為兩個子串行 sub lists 步驟為 1.從數列中挑出乙個元素,稱為 基準 pivot 2.重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面 相同的數可以到任一邊 在這個分...