クイックソートは、一般的に使用されるソート方法です。
迅速な並べ替えの考え方は次のとおりです。
まず、配列内の参照値を選択します。この参照値の機能は、配列全体を2つの部分に分割することです。この参照値より小さいすべての値は参照値の左側にあり、この参照値より大きいすべての値は参照値の右側にあります。
参考値未満 | 参照 | 基準値より大きい部分 |
次に、基準値より小さい部分と基準値より大きい部分に同じ方法を使用します。この部分までは分割できなくなります。これはクイックソートのアルゴリズムです。
例:整数配列が与えられた場合、高速メソッドを使用してソートします。
次に、クイックソートを開始します。デフォルトは昇順です。
以下は元のデータで、全部で10要素あります。として記録:
int originalData[10];
配列の内容を以下に示します。
1 | 10 | 3 | -12 | 51 | 23 | 1 | 4 | 12 | 4 |
最初のラウンド:
1.基準値を選択して、次のように記録します
int standardValue;
ここでは、最初の位置の要素を参照値として、
standardValue = 1;
2.要素にアクセスするには、2つの添え字が必要です。1つは0に初期化される左カーソルと呼ばれ、もう1つは9(配列長-1)に初期化される右カーソルと呼ばれます。
として記録:
左カーソル
int leftIndex = 0;
右カーソル
int rightIndex = 9;
3.右カーソルを右から左に移動させ、移動中に参照値standardValueより小さい値を見つけます。そのような値が見つかると、現時点では
rightIndex = 3;
originalData[rightIndex] = -12 < standardValue = 1;
4.右カーソルが示す位置の値を左カーソルが示す位置に配置します。
originalData[leftIndex] = originalData[rightIndex];
配列の状況は次のとおりです。
standardValue = 1;
leftIndex = 0;
rightIndex = 3;
配列の内容を以下に示します。
-12 | 10 | 3 | -12 | 51 | 23 | 1 | 4 | 12 | 4 |
5.左カーソルを左から右に移動させ、移動中に参照値standardValueより大きい値を見つけます。そのような値が見つかると、現時点では
leftIndex = 1;
originalData[leftIndex] = 10 > standardValue = 1;
6.左カーソルで示された位置の値を右カーソルで示された位置に置きます。
originalData[rightIndex] = originalData[leftIndex];
配列の状況は次のとおりです。
standardValue = 1;
leftIndex = 1;
rightIndex = 3;
-12 | 10 | 3 | 10 | 51 | 23 | 1 | 4 | 12 | 4 |
7.右カーソルを右から左に移動させ、移動中に参照値standardValueより小さい値を見つけます。結果は見つかりませんでした。
いつ
leftIndex = rightIndex
すると、このソートのラウンドは終了します。現時点では
leftIndex = rightIndex = 1;
-12 | 10 | 3 | 10 | 51 | 23 | 1 | 4 | 12 | 4 |
参照値を配列に戻す必要があります。それは
originalData[leftIndex] = standardValue = 1;
このとき、配列の内容は以下の通りです、
-12 | 1 | 3 | 10 | 51 | 23 | 1 | 4 | 12 | 4 |
第2ラウンド:
要素値1を線として使用して、配列を2つの部分に分割します。左側の部分は1以下で、右側の部分は1以上です。
-12 | 1 | 3 | 10 | 51 | 23 | 1 | 4 | 12 | 4 |
配列の左側にあるサブ配列(黄色の部分)を新しい配列として扱い、同じ操作を実行します。
-12 |
左側のサブアレイはすでに注文されています。
配列の右側にあるサブ配列(青い部分)を新しい配列として扱い、同じ操作を実行します。
3 | 10 | 51 | 23 | 1 | 4 | 12 | 4 |
同じ手順で、次のような結果が得られます。
1 | 3 | 51 | 23 | 10 | 4 | 12 | 4 |
第3ラウンド:
要素値3を線として使用して、配列を2つの部分に分割します。左側の部分は3以下であり、右側の部分は3以上です。
配列の左側にあるサブ配列(黄色の部分)を新しい配列として扱い、同じ操作を実行します。
1 |
配列の右側にあるサブ配列(青い部分)を新しい配列として扱い、同じ操作を実行します。
51 | 23 | 10 | 4 | 12 | 4 |
同じ手順で、次のような結果が得られます。
4 | 23 | 10 | 4 | 12 | 51 |
第4ラウンド:
要素値51を線として使用して、配列を2つの部分に分割します。左側の部分は51以下であり、右側の部分は51以上です。
左の部分だけが残っています。
配列の左側にあるサブ配列(黄色の部分)を新しい配列として扱い、同じ操作を実行します。
4 | 23 | 10 | 4 | 12 |
同じ手順で、次のような結果が得られます。
4 | 23 | 10 | 4 | 12 |
第5ラウンド:
要素値4を線として使用して、配列を2つの部分に分割します。左側の部分は4以下で、右側の部分は4以上です。
これで正しい部分だけが残りました。
23 | 10 | 4 | 12 |
同じ手順で、次のような結果が得られます。
12 | 10 | 4 | 23 |
第6ラウンド:
要素値23を線として使用して、配列を2つの部分に分割します。左側の部分は23以下であり、右側の部分は23以上です。
左の部分だけが残っています。
12 | 10 | 4 |
同じ手順で、次のような結果が得られます。
4 | 10 | 12 |
第7ラウンド:
要素値12を線として使用して、配列を2つの部分に分割します。左側の部分は12以下であり、右側の部分は12以上です。
左の部分だけが残っています。
4 | 10 |
残りの配列は正常です。
そして、すべての要素はすでに整然としているので、タスクは終わりです。
これらのサブ配列を位置順にまとめて、次の配列を取得します。
-12 | 1 | 1 | 3 | 4 | 4 | 10 | 12 | 23 | 51 |
元の配列は次のとおりです。
-12 | 10 | 3 | 10 | 51 | 23 | 1 | 4 | 12 | 4 |
並べ替えは正しい昇順の結果を得ました。(等しい値は相対位置を変更しないため、安定したソートアルゴリズムです)。
C ++コードの実装を以下に示します。ソースコードは参照用です。
#include <iostream>
using namespace std;
// 前向声明.
void quickSort(int *originalArray, int leftIndex, int rightIndex);
int main()
{
// 整数的个数.
int numbers = 0;
cin >> numbers;
// 保存整数的数组.
int *originalData = new int[numbers];
// 从标准输入中读取数据.
for (int i = 0; i < numbers; ++i)
{
cin >> originalData[i];
}
// 对数据进行排序.
// 使用二分排序法.
quickSort(originalData, 0, numbers - 1);
// 输出最小值和最大值.
cout << originalData[0] << " " << originalData[numbers - 1] << endl;
return 0;
}
void quickSort(int *originalArray, int leftIndex, int rightIndex)
{
// leftIndex 的备份.
int backLeft = leftIndex;
// rightIndex 的备份.
int backRight = rightIndex;
// 递归结束条件.
if (leftIndex > rightIndex)
{
// nothing to do.
}
else
{
// 参考标准.
int standardValue = originalArray[leftIndex];
while (leftIndex < rightIndex)
{
// 在 middleIndex 的右边部分,从后往前找到一个比 middleIndex 元素值小的元素.
while (leftIndex < rightIndex)
{
if (originalArray[rightIndex] >= standardValue)
{
// next element.
--rightIndex;
}
else
{
break;
}
}
originalArray[leftIndex] = originalArray[rightIndex];
// 在 middleIndex 的左边部分,从前往后找到一个比 middleIndex 元素值大的元素.
while (leftIndex < rightIndex)
{
if (originalArray[leftIndex] <= standardValue)
{
// next element.
++leftIndex;
}
else
{
break;
}
}
originalArray[rightIndex] = originalArray[leftIndex];
}
// 保存标准值.
originalArray[leftIndex] = standardValue;
// 递归调用自身.
quickSort(originalArray, backLeft, leftIndex - 1);
quickSort(originalArray, leftIndex + 1, backRight);
}
}
以下はJavaコードです。ソースコードは参照用です。
import java.util.Arrays;
import java.util.Scanner;
public class QuickSort
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int numbers = Integer.parseInt(scanner.nextLine());
int[] originalArray = new int[numbers];
for (int i = 0; i < numbers; ++i)
{
originalArray[i] = scanner.nextInt();
}
quickSort(originalArray, 0, numbers - 1);
System.out.println(Arrays.toString(originalArray));
scanner.close();
}
public static void quickSort(int[] originalData, int leftIndex, int rightIndex)
{
int backLeft = leftIndex;
int backRight = rightIndex;
if (leftIndex > rightIndex)
{
// nothing to do.
}
else
{
int standardValue = originalData[leftIndex];
while (leftIndex < rightIndex)
{
while (leftIndex < rightIndex)
{
if (originalData[rightIndex] >= standardValue)
{
// next element.
--rightIndex;
}
else
{
break;
}
}
originalData[leftIndex] = originalData[rightIndex];
while (leftIndex < rightIndex)
{
if (originalData[leftIndex] <= standardValue)
{
// next element.
++leftIndex;
}
else
{
break;
}
}
originalData[rightIndex] = originalData[leftIndex];
}
originalData[leftIndex] = standardValue;
// 递归调用自身.
quickSort(originalData, backLeft, leftIndex - 1);
quickSort(originalData, leftIndex + 1, backRight);
}
}
}
以上!