コンセプト
クイックソートソート交換属し、比較のための参照素子を使用する主なステップは、基準要素未満側にある移動させ、他方の側に、基準要素の移動よりも大きいです。アレイは、選択された二つの部分からの基準要素を削除する前に、上記の手順を繰り返すので、ことを2つの部分に分割されます。次のようにプロセスは以下のとおりです。
紫色:基準要素
グリーン:基準要素よりも大きい
イエロー:基準要素未満
このアイデアは、分割統治と呼ばれています。
参照要素
基準要素を選択し、ランダムに選択されてもよいです。ここで私は、基準要素として、要素の最初の使用を使用します。
注文プロセス
次のように図分解能ソーティングプロセスです。
ベース要素(再選択するために各ラウンド)などの紫
他の要素のための緑
最初のラウンド
第二ラウンド
第三ラウンド
:上に示した
、要素の数がnである場合、比較的再度あるソーティングプロセスが必要とするすべての要素ので、時間計算量はO(N)であり、
平均的なケースソーティングラウンドは、このように急速にソート平均、LOGNホイールを必要としました時間計算量はO(nlogn)です。
の実装の並べ替え
既存の二国間及び一方的ロビンロビンの実装
二国間ロビン
好ましい選択基準要素(ピボット)4、ポインタは、左右、以下のように左端の点列は、2つの要素を右端提供されます。
最初のサイクルは、データは右へのポインタを開始(rightData)は、比較および参照要素を開始
rightData> =ピボット、左に右に移動するが、rightData <ピボット場合、ポインタが左手に切り替え右に移動しない場合
左手基準要素との双方向データ(leftData)、leftData <ピボットは、右に左に移動し、leftData場合>場合に交換要素のピボット、左右ポイント。
ポインタの動きの最初のラウンドの後、以下の構造を得ました。
左右のポイントの要素にして、交換さ:
最初のサイクルが終了すると、右手にスイッチバックは、上記の手順を繰り返します。
サイクルの第2ラウンドの後、与えるために:
サイクルの第三ラウンドの後、得ました:
ループの第4ラウンドの後、あまりにも:
同一の要素に左右ポインタ点を分析、ポインタは、ポインタ要素及びピボット移動を停止与えるために交換。
ホイールサイクルが終了し、その後、ピボット要素、アレイの2つの部分とに応じて二つの部分に切断は、上記手順に従って動作宣言する。
実装コード
public class DoubleSort {
public static void quickSort(int[] arr, int startIndex, int endIndex) {
//递归结束条件
if (startIndex >= endIndex) {
return;
}
// 基准元素位置
int pivotIndex = partition(arr, startIndex, endIndex);
// 根据基准元素,分成两部分进行递归排序
quickSort(arr, startIndex, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, endIndex);
}
public static int partition(int[] arr, int startIndex, int endIndex) {
// 取第一个元素为基准元素,也可以随机抽取
int pivot = arr[startIndex];
int left = startIndex;
int right = endIndex;
while (left != right) {
// 控制right指针比较并左移
while (left < right && arr[right] >= pivot) {
right--;
}
// 控制left指针比较并右移
while (left < right && arr[left] <= pivot) {
left++;
}
// 交换left和right指针所指向的元素
if (left < right) {
int temp = arr[right];
arr[right] = arr[left];
arr[left] = temp;
}
}
arr[startIndex] = arr[left];
arr[left] = pivot;
return left;
}
public static void main(String[] args) {
int[] arr = new int[]{4, 7, 6, 5, 3, 2, 8, 1};
quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
片側ロビン
両側ロビン法の一の側からアレイを通して比較し、配列要素の両側からの交換、片側ループしながら、実施するのが比較的後方と交換より簡単でした。
次のようにプロセスは以下のとおりです。
ピボット要素は、第一の基準(ランダム選択)選択された
配列内の開始位置をマークするためのポインタを提供され、境界領域を表すことは少ない基準要素よりも(認識されないことが交換の他の要素のように使用されるものと理解されるであろう置きます)
元の配列は次の通り:
アレイを介して最初から基準要素
の要素素子が基準よりも大きい場合、トラバーサルはダウン継続
境界領域が少ない基準素子より1件の増加(すなわちより少ない基準素子よりなるので素子は、基準素子、右側にマークポインタよりも小さい場合複数の)+1にマーク、要素及びマーク点をスイッチング素子。
要素3,3 <4理由は、右のマークにトラバース
そして、スワップ・エレメント
次に、上記の判定ステップに応じて、後者の方法が書かれていない、トラバースし続けます。
実装コード
public class SingleSort {
public static void quickSort(int[] arr, int startIndex, int endIndex) {
//递归结束条件
if (startIndex >= endIndex) {
return;
}
// 基准元素位置
int pivotIndex = partition(arr, startIndex, endIndex);
// 根据基准元素,分成两部分进行递归排序
quickSort(arr, startIndex, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, endIndex);
}
/**
* 分治(单边循环法)
* @param arr
* @param startIndex
* @param endIndex
* @return
*/
public static int partition(int[] arr, int startIndex, int endIndex) {
// 取第一个元素为基准元素,也可以随机抽取
int pivot = arr[startIndex];
int mark = startIndex;
for(int i = startIndex + 1; i< arr.length; i++) {
if (pivot < arr[i]) {
continue;
}
mark ++;
int temp = arr[mark];
arr[mark] = arr[i];
arr[i] = temp;
}
arr[startIndex] = arr[mark];
arr[mark] = pivot;
return mark;
}
public static void main(String[] args) {
int[] arr = new int[]{4, 7, 6, 5, 3, 2, 8, 1};
quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
概要
ゆっくり書き込みアルゴリズムに彼の過去の本当に恥ずかしい、アルゴリズムのアイデアと実装を理解するためにした後、私は、また、アルゴリズムに新しいです。記事はまた、記事では、欠点を持っている場合、私はあなたが以下のコメントを追加するに懇願する、高速ロウアルゴリズムの自分の印象を深めます。お読みいただきありがとうございました。おかげ♪(・ω・)テクノ。
参考:「小さな灰色のアルゴリズムの旅」第IV章。
個人ブログのURL:https://colablog.cn/
あなたに私の記事が助けた場合、私は公共のマイクロチャネル番号、あなたの記事を共有するための最初の時間に集中することができます