一、快速排序介绍
クイックソート(クイックソート)は、分割統治法を使用します。その基本的な考え方は、基本番号を選択し、並べ替えパスを使用して並べ替えるデータを2つの独立した部分に分割することです。一方の部分のすべてのデータは、もう一方の部分のすべてのデータよりも小さくなります。次に、この方法に従って、データの2つの部分がすばやく別々にソートされ、ソートプロセス全体を再帰的に実行できるため、データ全体が順序付けられたシーケンスになります。
クイックソートプロセス:
- (1)シリーズから基準値を選びます。
- (2)ベンチマークの前に基準値よりも小さいすべての場所を置き、ベンチマークの後ろに基準値よりも大きいすべての場所を置きます(同じ数がどちらの側にも行くことができます)。パーティションが終了した後、ベンチマークはシリーズポジションの真ん中にあります。
- (3)「基準値前のサブシリーズ」と「基準値後のサブシリーズ」を再帰的にソートします。
二、快速排序图文说明
クイックソートコード
/*
* 快速排序
* * 参数说明:
* a -- 待排序的数组
* l -- 数组的左边界(例如,从起始位置开始排序,则l=0)
* r -- 数组的右边界(例如,排序截至到数组末尾,则r=a.length-1)
*/
void quick_sort(int a[], int l, int r)
{
if (l < r)
{
int i,j,x;
i = l;
j = r;
x = a[i];
while (i < j)
{
while(i < j && a[j] > x)
j--; // 从右向左找第一个小于x的数
if(i < j)
a[i++] = a[j];
while(i < j && a[i] < x)
i++; // 从左向右找第一个大于x的数
if(i < j)
a[j--] = a[i];
}
a[i] = x;
quick_sort(a, l, i-1); /* 递归调用 */
quick_sort(a, i+1, r); /* 递归调用 */
}
}
クイックソートプロセスを示す例として、シーケンスa = {30,40,60,10,20,50}を取り上げましょう(下の図を参照)。
上の図は、最初のクイックソートのフローのみを示しています。最初のパスで、x = a [i]、つまりx = 30を設定します。
-
(01)「右->左」からx未満の数を見つける:a [j] = 20、この時点ではj = 4を満たす数を見つけ、次にa [j]をa [i]に割り当てます。 、この時点でi = 0;次に、左から右にトラバースします。
-
(02)「左->右」からxより大きい数を見つける:a [i] = 40、次にi = 1を満たす数を見つけ、次にa [i]をa [j]に割り当て、次にj = 4;次に、右から左にトラバースします。
-
(03)「右->左」からx未満の数を見つける:a [j] = 10、次にj = 3の条件を満たす数を見つけ、次にa [j]をa [i]に割り当てます。次にi = 1;次に、左から右にトラバースします。
-
(04)「左->右」からxより大きい数を見つける:a [i] = 60、次にi = 2を満たす数を見つけ、次にa [i]をa [j]に割り当て、次にj = 3;次に、右から左にトラバースします。
-
(05)「右->左」からx未満の数を検索:条件を満たす数が見つかりません。i> = jの場合、検索を停止し、xをa [i]に割り当てます。このトラバーサルは終わりました!
同様に、サブシーケンスを再帰的にトラバースします。最後に、順序付けられた配列を取得します。
編集者は私自身のlinuxC / C ++言語技術交換グループを推奨しています:[ 1106675687 ]グループファイルで共有する方が良いと思う学習本とビデオ資料をいくつかまとめました。必要に応じて追加できます。
三、快速排序的时间复杂度和稳定性
クイックソートの安定性
クイックソートは、安定したアルゴリズムの定義を満たさない不安定なアルゴリズムです。
アルゴリズムの安定性-シーケンスにa [i] = a [j]があると仮定します。ソート前の場合、a [i]はa [j]の前にあり、ソート後、a [i]はまだa [j]の前にあります。そうすれば、このソートアルゴリズムは安定しています!
最悪の場合のクイックソート時間のクイックソート時間計算量はO(N2)であり、平均時間計算量はO(N * lgN)です。
この文は理解しやすいです。ソートされているシーケンスにN個の数字があるとします。1つのトラバーサルの時間計算量はO(N)です。トラバーサルはいくつ必要ですか?少なくともlg(N + 1)回、最大でN回。
- (01)なぜ少なくともlg(N + 1)回なのですか?クイックソートは分割統治法でトラバースされます。これを二分木と見なします。トラバースする必要がある回数は二分木の深さです。完全な二分木の定義によれば、その深さは少なくともlg(N + 1)。したがって、クイックソートのトラバーサル時間は少なくともlg(N + 1)回です。
- (02)なぜ最大でN回なのですか?これは非常に単純であるか、クイックソートを最大深度Nの二分木と考える必要があります。したがって、クイック読み取りソートのトラバーサルの数は最大でN回です。
四、快速排序实现
クイックソートCの実装
実装コード(quick_sort.c)
View Code
クイックソートC ++実装
実装コード(QuickSort.cpp)
View Code
クイックソートJava実装
実装コード(QuickSort.java)
View Code
上記の3つの言語の実装原則と出力結果は同じです。それらの出力は次のとおりです。
before sort:30 40 60 10 20 50
after sort:10 20 30 40 50 60