整列(Sort)-2
クイックソート
クイックソート(Quick Sort)は典型的な分割征服アルゴリズムであり,平均速度はO(N x logN)
であった.O(n^2)の選択、挿入、Bubbleソートと比較して、高速ソートアルゴリズムです.しかし,ある程度並べ替えが行われており,分割征服特性を利用できない特定の場合には,O(N^2)
の時間的複雑さがある可能性がある.
O(N x logN)
O(N^2)
例えば,O(N^2)の時間的複雑さがあると仮定する.
[1,2,3,4,5,6,7,8,9,10]のカウントは10 x 10=100であった.
半分を分割して征服すれば
[1,2,3,4,5]の場合、5 x 5=25
[6,7,8,9,10]の場合、5 x 5=25
25+25=50で、合計50回実行され、回数が減少します.
ステージ
まず簡単にまとめると,クイックソートは特定の基準値(Pivot)を基準として,大きな値と小さい値を互いに交換し,配列を半分に分ける方式である.以下の例で説明します.
3
とpivot値とが入れ替わる.大きい値(5)のインデックスは小さい値(1)のインデックスより小さいため、2つの値が互いに交換される.
このような手順を繰り返すと、ソートが完了します.この過程でよく考えてみると,パーティション征服がうまくいかなければ,性能が悪い原因も分かる.
インプリメンテーション
#include <stdio.h>
int number = 10;
int arr[] = {1, 3, 6, 9, 10, 4, 7, 8, 2, 5};
void quickSort(int *arr, int start, int end) {
if (start >= end) return;
int key = start; // 기준값(Pivot)
int i = start + 1;
int j = end;
int temp;
// 엇갈릴 때까지 반복
while (i <= j) {
// key보다 큰 값을 만날 때까지
while (arr[key] >= arr[i] && i <= end) {
i++;
}
// key보다 작은 값을 만날 때까지
while (arr[key] <= arr[j] && j > start) {
j--;
}
// 엇갈리면 작은 값과 key값 swap
if (i > j) {
temp = arr[key];
arr[key] = arr[j];
arr[j] = temp;
// 엇갈리지 않으면 i,j값 swap
} else {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// key값 기준으로 양쪽을 재귀로 분할 정복
quickSort(arr, start, j-1);
quickSort(arr, j+1, end);
}
int main() {
quickSort(arr, 0, number-1);
for (int i=0; i<number; ++i) {
printf("%d ", arr[i]);
}
return 0;
}
連結ソート
マージソート(Merge Sort)は、高速ソートと同様に、O(N x logN)
の時間的複雑さを有する典型的な分割征服アルゴリズムでもある.しかし、特定の場合にO(N^2)
という最悪時間の複雑さを持つ高速ソートとは異なり、マージソートはより多くのメモリを使用しているが、最悪の場合でもO(N x logN)
を保証できることが最大の特徴である.
ステージ
連結ソートの概念は、1つずつ分離するまで、すべて2つに分割し、連結時にソートを実行することです.
なぜ
logN
ですか?log(data의 개수)
-(ほぼ定数に等しい)N
ですか?N
だけがおかしいのか.これは、マージ後の古いコレクションが別々にソートされているためです.インプリメンテーション
#include <stdio.h>
int sorted[10];
void merge(int arr[], int m, int mid, int n) {
int i = m; // 앞 배열의 idx
int j = mid + 1; // 뒷 배열의 idx
int k = m; // sorted[]의 idx
// 작은 순서대로 sorted[]에 삽입, idx 증가
while (i <= mid && j <= n) {
if (arr[i] <= arr[j]) {
sorted[k] = arr[i];
i++;
} else {
sorted[k] = arr[j];
j++;
}
k++;
}
// 앞, 뒷 배열의 삽입이 먼저 완료될 때 나머지 데이터 삽입
if (i > mid) {
for (int t=j; t<=n; t++) {
sorted[k] = arr[t];
k++;
}
} else {
for (int t=i; t<=mid; t++) {
sorted[k] = arr[t];
k++;
}
}
// 임시로 sorted[]에 저장된 배열을 삽입
for (int t=m; t<=n; t++) {
arr[t] = sorted[t];
}
}
void mergeSort(int arr[], int m, int n) {
// 분할 정복(재귀)
if (m < n) {
int mid = (m + n) / 2;
mergeSort(arr, m, mid);
mergeSort(arr, mid+1, n);
merge(arr, m, mid, n);
}
}
int main() {
int arr[10] = {7, 6, 5, 8, 3, 5, 9, 1, 2, 10};
mergeSort(arr, 0, 9);
for (int i=0; i<10; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Reference
この問題について(整列(Sort)-2), 我々は、より多くの情報をここで見つけました https://velog.io/@leo-xee/정렬Sort-2テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol