1.コンセプト
クイック ソートの基本的な考え方は、1 回のソートでソート対象のレコードを 2 つの独立した部分に分割することです。レコードの一方の部分のキーワードがレコードのもう一方の部分のキーワードより小さい場合、2 つの部分はシーケンス全体を順序付けるという目的を達成するために並べ替えます。
2. アルゴリズムの考え方の説明
1. 除算を実行します。ベンチマーク (ピボット) を見つけ、ベンチマークより小さいレコードを後ろから前に検索し、見つかった場合は前に進み、次にベンチマークより大きいレコードを前から後ろに検索し、見つかった場合は後ろに進みます。ベンチマークが中心として使用されるまで、シーケンスは 2 つの部分に分割されます。つまり、ベンチマークの左側のレコードはベンチマークの右側のレコードよりも小さくなります。
2. 連続してシーケンスを 2 つの部分に分割し、シーケンスがそれ以上分割できなくなりシーケンス全体が整うまで、サブシーケンスをそれぞれ 2 つの部分に分割します。
1つの部門のアイデア:
3.コード
#include<iostream>
using namespace std;
int Partition(int* arr, int low, int high)//O(n)
{
int pivot = arr[low];//用子序列的第一个记录作为基准(枢轴)
while (low < high)//从序列的两端交替向中间扫描
{
//从后往前找比基准小的记录,找到往前移
while (low < high && arr[high] >= pivot) high--;
if (low < high)
{
arr[low++] = arr[high];
}
//从前往后找比基准大的记录,找到往后移
while (low < high && arr[low] <= pivot) low++;
if (low < high)
{
arr[high--] = arr[low];
}
}
arr[low] = pivot;//经过一次划分,将基准数字放在他该在的位置上(即基准左边的记录都小于基准右边的记录)
return low;//返回基准(枢轴)所在的位置
}
void Quick(int* arr, int low, int high)//O(nlogn)
{
if (low >= high) return;
int pivot = Partition(arr, low, high);//将基准进行一次划分,序列分为两份
Quick(arr, low, pivot - 1);//基准左边进行排序
Quick(arr, pivot + 1, high);//基准右边进行排序
}
void QuickSort(int* arr, int len)
{
Quick(arr, 0, len - 1);
}
void Show(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 9,3,12,6,7,10,5,8,21,4 };//待排序序列
int len = sizeof(arr) / sizeof(arr[0]);
QuickSort(arr, len);
printf("快速排序结果为:");
Show(arr, sizeof(arr) / sizeof(arr[0]));
return 0;
}
4.効率分析
時間計算量: O(nlogn)
スペースの複雑さ: O(logn) (再帰呼び出しスタック、再帰ログ回数のため)
安定性: 不安定
クイックソートの欠点
秩序があればあるほど遅くなり、空間の複雑さが増し、不安定になります。
シーケンスが昇順または降順の場合、クイックソートの時間と空間の複雑さは高くなります。
時間計算量: 1 回のソートの場合は O(n²) O(n)、再帰呼び出しの場合は O(n)
空間計算量: O(n) 再帰ツリーとして描画される場合、それはスキュー ツリーになります。