데이터 구조 : 공통 정렬 알고리즘 (6) : 빠른 정렬
1. 기본 아이디어 :
참조 요소 (일반적으로 첫 번째 요소 또는 마지막 요소)를 스캔 라운드를 통해 선택하면 정렬 할 시퀀스가 두 부분으로 나뉘어 하나는 참조 요소보다 작고 다른 하나는 참조 요소보다 크거나 같으며 그 안에 참조 요소가 정렬됩니다. 그런 다음 동일한 방법을 사용하여 각 간격에 숫자가 하나만있을 때까지 두 부분을 반복적으로 정렬합니다.
2. 예
예 : a [15] = {3,44,38,5,47,15,36,26,2,46,4,19,50,48} 배열은 빠른 정렬로 정렬됩니다.
이미지 출처 : https://www.cnblogs.com/zwtgyh/p/10631760.html
예제 코드 :
//辅助函数:交换值
void exchange(int * a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
//打印数组函数
void print_arr(int *a, int size)
{
cout << "打印数组:";
for (int i = 0; i<size; i++) //打印数组
{
cout << a[i] << " ";
}
cout << endl << endl;
}
/*序列划分函数*/
int partition(int a[], int p, int r) {
int key = a[r];//取最后一个
int i = p - 1;
for (int j = p; j < r; j++)
{
if (a[j] <= key)
{
i++;
//i一直代表小于key元素的最后一个索引,当发现有比key小的a[j]时候,i+1 后交换
exchange(&a[i], &a[j]);
}
}
exchange(&a[i + 1], &a[r]);//将key切换到中间来,左边是小于key的,右边是大于key的值。
return i + 1;
}
void quickSort(int a[], int p, int r) {
int position = 0;
if (p<r)
{
position = partition(a,p,r);//返回划分元素的最终位置
quickSort(a,p,position-1);//划分左边递归
quickSort(a, position + 1,r);//划分右边递归
}
}
//主函数
void main() {
int a[15]={3,44,38,5,47,15,36,26,2,46,4,19,50,48};
cout << "输入数组 a[15]={3,44,38,5,47,15,36,26,2,46,4,19,50,48} " << endl;
quickSort(a, 0, 14);
print_arr(a, 15);
}
3. 요약 :
- 가장 좋은 경우 : 각 분할 라운드는 정렬 할 시퀀스를 두 부분으로 나누므로 각 부분에 필요한 시간은 이전 라운드의 1/2입니다. n 개의 요소 시퀀스가 정렬 된 경우 재귀 트리의 깊이는 [logn] +1입니다. 즉, logn 재귀 만 필요하고 총 필요한 시간은 T (n)입니다. 처음 전체 시퀀스를 스캔해야 할 때 n 개의 비교를 수행 한 다음 시퀀스는 두 개로 나뉘고 두 부분은 각각 T (n / 2) 시간이 필요하며 순서대로 나뉩니다. T (n) = 2 T (n / 2) + n T (n) = 2 (2 * (T (n / 4) + n / 2) + n = 4 T (n / 4) + 2n 등, T (1) = 0이므로 T (n) = n T (1) + n * logn = O (nlogn)
- 최악의 경우 : 정렬 할 시퀀스가 순서가 지정된 시퀀스 (양수 또는 역순) 인 경우 각 분할 후 얻은 상황은 한쪽에 1 개의 요소가 있고 다른쪽에 나머지 요소가 있으며 마지막으로 n-1 라운드의 루핑입니다. , 그리고 i 번째 사이클은 ni 비교가 필요합니다. 총 비교 횟수는 n-1 + n-2 +… + 1 = n (n-1) / 2, 즉 시간 복잡도는 O (n ^ 2)입니다.
- 빠른 정렬은 현장 정렬이며 추가 메모리 공간이 필요하지 않습니다.
- 빠른 정렬은 안정적인 정렬이 아니며 교환 과정에서 안정성을 파괴합니다.