アルゴリズムのクイックソート
@author:Jingdai
@date:2020.10.28
今日LeetCodeをスワイプしたところ、以前に学んだクイックソートを忘れていたことがわかりました。今すぐ記録してください。今後も忘れないようにしたいと思います。
前書き
クイックソート、つまりクイックソート。まあ、言うまでもなく、思考の流れを見てください。
アイデア
1つの文のアイデアは、配列内の数値を決定し、
pivot
それよりも小さいすべての数値をその左側に配置し、それよりも大きいすべての数値を右側に配置することです。次に、左側のサブ配列と右側のサブ配列で同じアルゴリズムを再帰的に呼び出して、並べ替えを完了します。次のコードスニペットを参照してください。public static void quickSort(int[] array, int left, int right) { if (left >= right) { return; } int pivot = positionAndGetPivot(array, left, right); quickSort(array, left, pivot - 1); quickSort(array, pivot + 1, right); }
上記のコードを見ると、実際のところ、主な問題は1つを選択
pivot
し、左側にそれよりも小さい数を、右側にそれよりも大きい数を配置することであることがわかります。それの番号pivot
についてのその選択?簡単にするために、最初に左端の配列として選択しpivot
、次に2つのポインター変数left
とright
配列の左端の添え字を選択し、右端のインデックスを記録します。示されているように、pivot
数字の小さい数字よりも小さい数字を見つけて左に移動し、次に左からpivot
数字の大きい数字を見つけるよりも右から始めて、サイクルがleft
等しくなるまで右に移動しますright
。次に、pivot
値を置くleft
ことができる(この時点で位置left
とright
同じです)。実際、プロセス全体は、アルゴリズムが2つの変数値を交換するのと少し似ています。中間変数を使用する必要がありますが、ここではレコード変数pivot
値を使用し、その右側にあるその位置の番号を見つけるための適切な場所を使用します。位置と、他の番号を入れて、左から右に番号PUTを探すことができるまでleft
とright
等しい、その後に記録されている元の中間変数pivot
この位置に配置された値。以下のコードスニペットを見てください。
public static int positionAndGetPivot(int[] array, int left, int right) { int pivotValue = array[left]; while (left < right) { while (left < right && array[right] >= pivotValue) { right --; } array[left] = array[right]; while (left < right && array[left] <= pivotValue) { left ++; } array[right] = array[left]; } array[left] = pivotValue; return left; }
ただし、上記のコードには少し問題があります。配列内の数値のランダム性が良くない場合、高速ソートの効率はあまり理想的ではありません。ここでは、手動でランダム性を導入できます。上記のよう
pivot
に配列の左端の数値を選択するたびに、配列のpivot
ランダム性が不十分なために発生する効率の問題を防ぐために、ランダムに選択できます。それは非常に単純だ、left
とright
ランダムインデックスとして1を選択しpivot
、その後の選択数array[left]
、参照してください。次のコードスニペットのように交換しました。public static int positionAndGetPivot(int[] array, int left, int right) { Random r = new Random(); int pivotIndex = r.nextInt(right - left + 1) + left; int pivotValue = array[pivotIndex]; array[pivotIndex] = array[left]; while (left < right) { while (left < right && array[right] >= pivotValue) { right --; } array[left] = array[right]; while (left < right && array[left] <= pivotValue) { left ++; } array[right] = array[left]; } array[left] = pivotValue; return left; }
pivot
選択した位置の機能の完了後、このアルゴリズムを再帰的に呼び出すことで、すばやく並べて完了することができます。完全なコードは次のとおりです。
コード
public static void main(String[] args){ int[] array = { 4, 5, 9, 2, 1, 4, 1, 3, 5, 6, 7}; quickSort(array); System.out.println(Arrays.toString(array)); } public static void quickSort(int[] array) { quickSort(array, 0, array.length-1); } public static void quickSort(int[] array, int left, int right) { if (left >= right) { return; } int pivot = positionAndGetPivot(array, left, right); quickSort(array, left, pivot - 1); quickSort(array, pivot + 1, right); } public static int positionAndGetPivot(int[] array, int left, int right) { Random r = new Random(); int pivotIndex = r.nextInt(right - left + 1) + left; int pivotValue = array[pivotIndex]; array[pivotIndex] = array[left]; while (left < right) { while (left < right && array[right] >= pivotValue) { right --; } array[left] = array[right]; while (left < right && array[left] <= pivotValue) { left ++; } array[right] = array[left]; } array[left] = pivotValue; return left; }