當前位置:首頁 » 操作系統 » c快速排序演算法

c快速排序演算法

發布時間: 2022-09-09 19:53:25

1. 快速排序演算法的排序演示

假設用戶輸入了如下數組: 下標 0 1 2 3 4 5 數據 6 2 7 3 8 9 創建變數i=0(指向第一個數據), j=5(指向最後一個數據), k=6(賦值為第一個數據的值)。
我們要把所有比k小的數移動到k的左面,所以我們可以開始尋找比6小的數,從j開始,從右往左找,不斷遞減變數j的值,我們找到第一個下標3的數據比6小,於是把數據3移到下標0的位置,把下標0的數據6移到下標3,完成第一次比較: 下標 0 1 2 34 5 數據 3 2 7 6 8 9 i=0 j=3 k=6
接著,開始第二次比較,這次要變成找比k大的了,而且要從前往後找了。遞加變數i,發現下標2的數據是第一個比k大的,於是用下標2的數據7和j指向的下標3的數據的6做交換,數據狀態變成下表: 下標 0 1 2 3 4 5 數據 3 2 6 7 8 9 i=2 j=3 k=6
稱上面兩次比較為一個循環。
接著,再遞減變數j,不斷重復進行上面的循環比較。
在本例中,我們進行一次循環,就發現i和j「碰頭」了:他們都指向了下標2。於是,第一遍比較結束。得到結果如下,凡是k(=6)左邊的數都比它小,凡是k右邊的數都比它大: 下標 0 1 2 3 4 5 數據 3 2 6 7 8 9 如果i和j沒有碰頭的話,就遞加i找大的,還沒有,就再遞減j找小的,如此反復,不斷循環。注意判斷和尋找是同時進行的。
然後,對k兩邊的數據,再分組分別進行上述的過程,直到不能再分組為止。
注意:第一遍快速排序不會直接得到最終結果,只會把比k大和比k小的數分到k的兩邊。為了得到最後結果,需要再次對下標2兩邊的數組分別執行此步驟,然後再分解數組,直到數組不能再分解為止(只有一個數據),才能得到正確結果。 在c++中可以用函數qsort()可以直接為數組進行排序。
用 法:
void qsort(void *base, int nelem, int width, int (*fcmp)(const void *,const void *));
參數:1 待排序數組首地址2 數組中待排序元素數量3 各元素的佔用空間大小4 指向函數的指針,用於確定排序的順序

2. 排序演算法有哪些,簡述快速排序的核心

簡單的: 冒泡,選擇排序,插入排序,桶排序,

復雜點的: 堆排序,歸並排序,快速排序,

還有基數排序,計數排序(這兩個我還沒接觸到,不懂)

快速排序核心:

每次排序的時候設置一個基準點,將小於等於基準點的數全部放到基準點的左邊,將大於等於基準點的數全部放到基準點的右邊。這樣在每次交換的時候就不會像冒泡排序一樣只能在相鄰的數之間進行交換,交換的距離就大得多了。因此總的比較和交換次數就少了,速度自然就提高了。

圖片及快速排序簡述來源於<啊哈演算法>

3. 快速排序法的平均時間復雜度和最壞時間復雜度分別是多少

快速排序的平均時間復雜度和最壞時間復雜度分別是O(nlgn)、O(n^2)。

當排序已經成為基本有序狀態時,快速排序退化為O(n^2),一般情況下,排序為指數復雜度。

快速排序最差情況遞歸調用棧高度O(n),平均情況遞歸調用棧高度O(logn),而不管哪種情況棧的每一層處理時間都是O(n),所以,平均情況(最佳情況也是平均情況)的時間復雜度O(nlogn),最差情況的時間復雜度為O(n^2)。



(3)c快速排序演算法擴展閱讀

快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序,它採用了一種分治的策略,通常稱其為分治法。快速排序演算法通過多次比較和交換來實現排序,其排序流程如下:

(1)首先設定一個分界值,通過該分界值將數組分成左右兩部分。

(2)將大於或等於分界值的數據集中到數組右邊,小於分界值的數據集中到數組的左邊。此時,左邊部分中各元素都小於或等於分界值,而右邊部分中各元素都大於或等於分界值。

(3)然後,左邊和右邊的數據可以獨立排序。對於左側的數組數據,又可以取一個分界值,將該部分數據分成左右兩部分,同樣在左邊放置較小值,右邊放置較大值。右側的數組數據也可以做類似處理。

(4)重復上述過程,可以看出,這是一個遞歸定義。通過遞歸將左側部分排好序後,再遞歸排好右側部分的順序。當左、右兩個部分各數據排序完成後,整個數組的排序也就完成了。

4. 快速排序法

快速排序(Quicksort)是對冒泡排序的一種改進。[1]

快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。[1]

中文名
快速排序演算法
外文名
quick sort
別名
快速排序
提出者
C. A. R. Hoare
提出時間
1960年
快速
導航
排序步驟

程序調用舉例

示例代碼

性能分析
排序流程
快速排序演算法通過多次比較和交換來實現排序,其排序流程如下:[2]
(1)首先設定一個分界值,通過該分界值將數組分成左右兩部分。[2]
(2)將大於或等於分界值的數據集中到數組右邊,小於分界值的數據集中到數組的左邊。此時,左邊部分中各元素都小於或等於分界值,而右邊部分中各元素都大於或等於分界值。[2]
(3)然後,左邊和右邊的數據可以獨立排序。對於左側的數組數據,又可以取一個分界值,將該部分數據分成左右兩部分,同樣在左邊放置較小值,右邊放置較大值。右側的數組數據也可以做類似處理。[2]
(4)重復上述過程,可以看出,這是一個遞歸定義。通過遞歸將左側部分排好序後,再遞歸排好右側部分的順序。當左、右兩個部分各數據排序完成後,整個數組的排序也就完成了。[2]
排序步驟
原理
設要排序的數組是A[0]……A[N-1],首先任意選取一個數據(通常選

快排圖
用數組的第一個數)作為關鍵數據,然後將所有比它小的數都放到它左邊,所有比它大的數都放到它右邊,這個過程稱為一趟快速排序。值得注意的是,快速排序不是一種穩定的排序演算法,也就是說,多個相同的值的相對位置也許會在演算法結束時產生變動。[1]
一趟快速排序的演算法是:[1]
1)設置兩個變數i、j,排序開始的時候:i=0,j=N-1;[1]
2)以第一個數組元素作為關鍵數據,賦值給key,即key=A[0];[1]
3)從j開始向前搜索,即由後開始向前搜索(j--),找到第一個小於key的值A[j],將A[j]和A[i]的值交換;[1]
4)從i開始向後搜索,即由前開始向後搜索(i++),找到第一個大於key的A[i],將A[i]和A[j]的值交換;[1]
5)重復第3、4步,直到i==j; (3,4步中,沒找到符合條件的值,即3中A[j]不小於key,4中A[i]不大於key的時候改變j、i的值,使得j=j-1,i=i+1,直至找到為止。找到符合條件的值,進行交換的時候i, j指針位置不變。另外,i==j這一過程一定正好是i+或j-完成的時候,此時令循環結束)。[1]
排序演示
假設一開始序列{xi}是:5,3,7,6,4,1,0,2,9,10,8。
此時,ref=5,i=1,j=11,從後往前找,第一個比5小的數是x8=2,因此序列為:2,3,7,6,4,1,0,5,9,10,8。
此時i=1,j=8,從前往後找,第一個比5大的數是x3=7,因此序列為:2,3,5,6,4,1,0,7,9,10,8。
此時,i=3,j=8,從第8位往前找,第一個比5小的數是x7=0,因此:2,3,0,6,4,1,5,7,9,10,8。

5. 快速排序特點

快速排序(Quicksort)是對冒泡排序的一種改進,由東尼·霍爾在1960年提出。 快速排序是指通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序。整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。

分類
排序演算法

數據結構
不定

最壞空間復雜度
根據實現的方式不同而不同
快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。

步驟為:

從數列中挑出一個元素,稱為「基準」(pivot),

重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準後面(相同的數可以到任何一邊)。在這個分區結束之後,該基準就處於數列的中間位置。這個稱為分區(partition)操作。

遞歸地(recursively)把小於基準值元素的子數列和大於基準值元素的子數列排序。

遞歸到最底部時,數列的大小是零或一,也就是已經排序好了。這個演算法一定會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。

在簡單的偽代碼中,此演算法可以被表示為:

function quicksort(q)
{
var list less, pivotList, greater
if length(q) ≤ 1
return q
else
{
select a pivot value pivot from q
for each x in q except the pivot element
{
if x<pivot then add x to less
if x ≥ pivot then add x to greater
}
add pivot to pivotList
return concatenate(quicksort(less), pivotList, quicksort(greater))
}
}
原地(in-place)分區的版本

上面簡單版本的缺點是,它需要的額外存儲空間,也就跟歸並排序一樣不好。額外需要的存儲器空間配置,在實際上的實現,也會極度影響速度和緩存的性能。有一個比較復雜使用原地(in-place)分區演算法的版本,且在好的基準選擇上,平均可以達到空間的使用復雜度。

function partition(a, left, right, pivotIndex)
{
pivotValue = a[pivotIndex]
swap(a[pivotIndex], a[right]) // 把pivot移到結尾
storeIndex = left
for i from left to right-1
{
if a[i]<= pivotValue
{
swap(a[storeIndex], a[i])
storeIndex = storeIndex + 1
}
}
swap(a[right], a[storeIndex]) // 把pivot移到它最後的地方
return storeIndex
}
這是原地分區演算法,它分區了標示為"左邊(left)"和"右邊(right)"的序列部分,藉由移動小於的所有元素到子序列的開頭,留下所有大於或等於的元素接在他們後面。在這個過程它也為基準元素找尋最後擺放的位置,也就是它回傳的值。它暫時地把基準元素移到子序列的結尾,而不會被前述方式影響到。由於演算法只使用交換,因此最後的數列與原先的數列擁有一樣的元素。要注意的是,一個元素在到達它的最後位置前,可能會被交換很多次。

一旦我們有了這個分區演算法,要寫快速排列本身就很容易:

procere quicksort(a, left, right)
if right>left
select a pivot value a[pivotIndex]
pivotNewIndex := partition(a, left, right, pivotIndex)
quicksort(a, left, pivotNewIndex-1)
quicksort(a, pivotNewIndex+1, right)
這個版本經常會被使用在命令式語言中,像是C語言。

快速排序
快速排序是二叉查找樹(二叉搜索樹)的一個空間最優化版本。不是循序地把數據項插入到一個明確的樹中,而是由快速排序組織這些數據項到一個由遞歸調用所隱含的樹中。這兩個演算法完全地產生相同的比較次數,但是順序不同。對於排序演算法的穩定性指標,原地分區版本的快速排序演算法是不穩定的。其他變種是可以通過犧牲性能和空間來維護穩定性的。

6. 快速排序演算法原理與實現

快速排序的原理:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小。

然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。

假設要排序的數組是A[1]……A[N],首先任意選取一個數據(通常選用第一個數據)作為關鍵數據,然後將所有比它的數都放到它前面,所有比它大的數都放到它後面,這個過程稱為一躺快速排序。一躺快速排序的演算法是:

1、設置兩個變數I、J,排序開始的時候I:=1,J:=N;

2、以第一個數組元素作為關鍵數據,賦值給X,即X:=A[1];

3、從J開始向前搜索,即由後開始向前搜索(J:=J-1),找到第一個小於X的值,兩者交換;

4、從I開始向後搜索,即由前開始向後搜索(I:=I+1),找到第一個大於X的值,兩者交換;

5、重復第3、4步,直到I=J。

(6)c快速排序演算法擴展閱讀:

設要排序的數組是A[0]……A[N-1],首先任意選取一個數據(通常選用數組的第一個數)作為關鍵數據,然後將所有比它小的數都放到它前面,所有比它大的數都放到它後面,這個過程稱為一趟快速排序。

值得注意的是,快速排序不是一種穩定的排序演算法,也就是說,多個相同的值的相對位置也許會在演算法結束時產生變動。

一趟快速排序的演算法是:

1、設置兩個變數i、j,排序開始的時候:i=0,j=N-1;

2、以第一個數組元素作為關鍵數據,賦值給key,即key=A[0];

3、從j開始向前搜索,即由後開始向前搜索(j--),找到第一個小於key的值A[j],將A[j]的值賦給A[i];

4、從i開始向後搜索,即由前開始向後搜索(i++),找到第一個大於key的A[i],將A[i]的值賦給A[j];

5、重復第3、4步,直到i=j; (3,4步中,沒找到符合條件的值,即3中A[j]不小於key,4中A[i]不大於key的時候改變j、i的值,使得j=j-1,i=i+1,直至找到為止。找到符合條件的值,進行交換的時候i, j指針位置不變。

7. 快速排序的原理是什麼


數據序列

元素,並
序列

比該元素
元素都放
右邊或左邊,再
左右兩邊
別用同



待處理
序列

1,
處理結束

序區R[1..H]
任取
數據元素作
比較
"基準"(
妨記
X)

基準

序區劃
左右兩

序區:R[1..I-1]
R[I+1..H]
且左邊


數據元素均
於等於基準元素
右邊


數據元素均
於等於基準元素
基準X則位於
終排序
位置
即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H)
R[1..I-1]
R[I+1..H]均非空

進行



直至所


數據元素均已排序

快速排序
基本思想
基於
治策略
於輸入
序列L[p..r]
規模足夠
則直接進行排序(比
用前述
冒泡、選擇、插入排序均

否則
三步處理:
解(Divide):
待排序列L[p..r]劃

非空
序列L[p..q]
L[q+1..r]
使L[p..q]

元素

於L[q+1..r]

元素

具體

途徑實現:
序列L[p..r]
選擇數據元素L[q]
經比較

L[q]
處於L[p..r]


位置
使
數據元素L[q]

於L[q+1..r]

元素

遞歸求解(Conquer):通
遞歸調用快速排序算

L[p..q]
L[q+1..r]進行排序
合並(Merge):由於


序列
排序
進行

L[p..q]
L[q+1..r]都排

需要執行任何計算L[p..r]
已排

即自
合並
解決流程
符合

基本步驟
快速排序

經典應用實例

8. 快速排序的復雜度怎麼算,是多少

這個,我確實一點也不懂,幫你搜索。

1.
快速排序-時空復雜度:
快速排序每次將待排序數組分為兩個部分,在理想狀況下,每一次都將待排序數組劃分成等長兩個部分,則需要logn次劃分。
而在最壞情況下,即數組已經有序或大致有序的情況下,每次劃分只能減少一個元素,快速排序將不幸退化為冒泡排序,所以快速排序時間復雜度下界為O(nlogn),最壞情況為O(n^2)。在實際應用中,快速排序的平均時間復雜度為O(nlogn)。
快速排序在對序列的操作過程中只需花費常數級的空間。空間復雜度S(1)。
但需要注意遞歸棧上需要花費最少logn最多n的空間。

2.快速排序-隨機化演算法:
快速排序的實現需要消耗遞歸棧的空間,而大多數情況下都會通過使用系統遞歸棧來完成遞歸求解。在元素數量較大時,對系統棧的頻繁存取會影響到排序的效率。
一種常見的辦法是設置一個閾值,在每次遞歸求解中,如果元素總數不足這個閾值,則放棄快速排序,調用一個簡單的排序過程完成該子序列的排序。這樣的方法減少了對系統遞歸棧的頻繁存取,節省了時間的消費。
一般的經驗表明,閾值取一個較小的值,排序演算法採用選擇、插入等緊湊、簡潔的排序。一個可以參考的具體方案:閾值T=10,排序演算法用選擇排序。
閾值不要太大,否則省下的存取系統棧的時間,將會被簡單排序演算法較多的時間花費所抵消。
另一個可以參考的方法,是自行建棧模擬遞歸過程。但實際經驗表明,收效明顯不如設置閾值。

3.快速排序的最壞情況基於每次劃分對主元的選擇。基本的快速排序選取第一個元素作為主元。這樣在數組已經有序的情況下,每次劃分將得到最壞的結果。一種比較常見的優化方法是隨機化演算法,即隨機選取一個元素作為主元。這種情況下雖然最壞情況仍然是O(n^2),但最壞情況不再依賴於輸入數據,而是由於隨機函數取值不佳。實際上,隨機化快速排序得到理論最壞情況的可能性僅為1/(2^n)。所以隨機化快速排序可以對於絕大多數輸入數據達到O(nlogn)的期望時間復雜度。一位前輩做出了一個精闢的總結:「隨機化快速排序可以滿足一個人一輩子的人品需求。」
隨機化快速排序的唯一缺點在於,一旦輸入數據中有很多的相同數據,隨機化的效果將直接減弱。對於極限情況,即對於n個相同的數排序,隨機化快速排序的時間復雜度將毫無疑問的降低到O(n^2)。解決方法是用一種方法進行掃描,使沒有交換的情況下主元保留在原位置。

4.設要排序的數組是A[0]……A[N-1],首先任意選取一個數據(通常選用第一個數據)作為關鍵數據,然後將所有比它小的數都放到它前面,所有比它大的數都放到它後面,這個過程稱為一趟快速排序。一趟快速排序的演算法是:
1)設置兩個變數I、J,排序開始的時候:I=0,J=N-1;
2)以第一個數組元素作為關鍵數據,賦值給key,即 key=A[0];
3)從J開始向前搜索,即由後開始向前搜索(J=J-1),找到第一個小於key的值A[J],並與A[I]交換;
4)從I開始向後搜索,即由前開始向後搜索(I=I+1),找到第一個大於key的A[I],與A[J]交換;
5)重復第3、4、5步,直到 I=J; (3,4步是在程序中沒找到時候j=j-1,i=i+1。找到並交換的時候i, j指針位置不變。另外當i=j這過程一定正好是i+或j+完成的最後另循環結束)
例如:待排序的數組A的值分別是:(初始關鍵數據:X=49) 注意關鍵X永遠不變,永遠是和X進行比較,無論在什麼位子,最後的目的就是把X放在中間,小的放前面大的放後面。
A[0] 、 A[1]、 A[2]、 A[3]、 A[4]、 A[5]、 A[6]:
49 38 65 97 76 13 27
進行第一次交換後: 27 38 65 97 76 13 49
( 按照演算法的第三步從後面開始找)
進行第二次交換後: 27 38 49 97 76 13 65
( 按照演算法的第四步從前面開始找>X的值,65>49,兩者交換,此時:I=3 )
進行第三次交換後: 27 38 13 97 76 49 65
( 按照演算法的第五步將又一次執行演算法的第三步從後開始找
進行第四次交換後: 27 38 13 49 76 97 65
( 按照演算法的第四步從前面開始找大於X的值,97>49,兩者交換,此時:I=4,J=6 )
此時再執行第三步的時候就發現I=J,從而結束一趟快速排序,那麼經過一趟快速排序之後的結果是:27 38 13 49 76 97 65,即所以大於49的數全部在49的後面,所以小於49的數全部在49的前面。
快速排序就是遞歸調用此過程——在以49為中點分割這個數據序列,分別對前面一部分和後面一部分進行類似的快速排序,從而完成全部數據序列的快速排序,最

9. 快速排序演算法在平均情況下的時間復雜度為 求詳解

時間復雜度為O(nlogn) n為元素個數
1. 快速排序的三個步驟:
1.1. 找到序列中用於劃分序列的元素
1.2. 用元素劃分序列
1.3. 對劃分後的兩個序列重復1,2兩個步驟指導序列無法再劃分
所以對於n個元素其排序時間為
T(n) = 2*T(n/2) + n (表示將長度為n的序列劃分為兩個子序列,每個子序列需要T(n/2)
的時間,而劃分序列需要n的時間)
而 T(1) = 1 (表示長度為1的序列無法劃分子序列,只需要1的時間即可)
T(n) = 2^logn + logn * n (n被不斷二分最終只能二分logn次(最優的情況,每次選取
的元素都均分序列))
= n + nlogn
因此T(n) = O(nlogn)
以上是最優情況的推導,因此快速排序在最優情況下其排序時間為O(nlogn),通常平均情況
我們也認為是此值。
在最壞情況下其會退化為冒泡排序,T(n) = T(n - 1) + n (每次選取的元素只能將序列劃分為
一段,即自身是 最小元素或最大元素)
因此T(n) = n * (n-1) / 2 相當於O(n^2)

10. 快速排序演算法

快速排序(Quicksort)是對冒泡排序的一種改進。

然後,左邊和右邊的數據可以獨立排序。對於左側的數組數據,又可以取一個分界值,將該部分數據分成左右兩部分,同樣在左邊放置較小值,右邊放置較大值。右側的數組數據也可以做類似處理。

重復上述過程,可以看出,這是一個遞歸定義。通過遞歸將左側部分排好序後,再遞歸排好右側部分的順序。當左、右兩個部分各數據排序完成後,整個數組的排序也就完成了。

快速排序演算法通過多次比較和交換來實現排序,其排序流程如下:

(1)首先設定一個分界值,通過該分界值將數組分成左右兩部分。

(2)將大於或等於分界值的數據集中到數組右邊,小於分界值的數據集中到數組的左邊。此時,左邊部分中各元素都小於或等於分界值,而右邊部分中各元素都大於或等於分界值。


熱點內容
app什麼情況下找不到伺服器 發布:2025-05-12 15:46:25 瀏覽:714
php跳過if 發布:2025-05-12 15:34:29 瀏覽:467
不定時演算法 發布:2025-05-12 15:30:16 瀏覽:131
c語言延時1ms程序 發布:2025-05-12 15:01:30 瀏覽:165
動物園靈長類動物配置什麼植物 發布:2025-05-12 14:49:59 瀏覽:734
wifi密碼設置什麼好 發布:2025-05-12 14:49:17 瀏覽:148
三位數乘兩位數速演算法 發布:2025-05-12 13:05:48 瀏覽:397
暴風影音緩存在哪裡 發布:2025-05-12 12:42:03 瀏覽:541
access資料庫exe 發布:2025-05-12 12:39:04 瀏覽:629
五開的配置是什麼 發布:2025-05-12 12:36:37 瀏覽:365