Shell 정렬
Shell 정렬은 매우 효율적인 비교 기반 정렬 알고리즘입니다. 버블 정렬 알고리즘의 일반화 또는 최적화 된 삽입 정렬 알고리즘으로 간주됩니다. 삽입 정렬 알고리즘에서 요소를 한 위치 앞으로 이동합니다. 그러나 Shell 정렬의 경우 요소 h
위치를 앞으로 이동합니다. 매우 먼 요소를 정렬하는 것으로 시작하여 전체 배열을 정렬하는 순서에 따라 간격을 점차적으로 줄입니다. 사용되는 일부 시퀀스는 다음과 같습니다.
Shell의 원래 시퀀스 | N/2, N/4, ..., 1 |
Papernov & Stasevich | 1, 3, 5, 9,... |
Hibbard | 1, 3, 7, 15, 31, 63,... |
Knuth | 1, 4, 13, ... , (3k – 1) / 2 |
Pratt | 1, 2, 3, 4, 6, 9, 8, 12, 18, 27, 16, .... |
Sedgewick | 1, 8, 23, 77, 281, ... 4j+1+ 3·2j+ 1 |
Shell 정렬 알고리즘
n
요소를 포함하는 정렬되지 않은 배열A[]
가 있다고 가정 해 보겠습니다. 셸의 원래 시퀀스를 사용하여 배열을 정렬합니다.
-
시퀀스에 따라 ‘갭’값을 계산합니다.
-
간격
과 같은 간격의 모든 하위 배열에 대해 다음을 수행합니다. -
삽입 정렬을 사용하여 정렬합니다.
-
전체 배열이 정렬 될 때까지 위 과정을 반복합니다.
Shell 정렬 예
배열이(9, 8, 3, 7, 5, 6, 4, 1)
이라고 가정합니다. Shell 정렬 알고리즘을 사용하여 정렬하고 쉘의 원래 시퀀스를 사용하여 간격 간격을 줄입니다.
- 첫 번째 반복
n/2
= 4, 간격4
에있는 요소가 비교되고 교체됩니다.
A[0]
>A[4]
→ 교체 됨,(5,8,3,7,9,6,4,1)
.
A[1]
>A[5]
→ 교체 됨,(5,6,3,7,9,8,4,1)
.
A[2]
<A[6]
A[3]
>A[7]
→ 교체 됨,(5,6,3,1,9,8,4,7)
.
배열은(5,6,3,1,9,8,4,7)
이됩니다.
- 두 번째 반복
n/4
= 2,2
간격에있는 요소가 비교되고 교체됩니다.
A[0]
>A[2]
→ 교체 됨,(3,6,5,1,9,8,4,7)
.
A[1]
>A[3]
→ 교체 됨,(3,1,5,6,9,8,4,7)
.
A[0]
<A[2]
<A[4]
A[1]
<A[3]
<A[5]
A[2]
>A[4]
및A[4]
>A[6]
→ 교체 됨,(3,1,4,6,5,8,9,7)
.
A[1]
<A[3]
<A[5]
그러나A[5]
>A[7]
→ 교체 됨,(3,1,4,6,5,7 , 9,8)
.
배열은(3,1,4,6,5,7,9,8)
이됩니다.
- 세 번째 반복
n/8
= 1,1
간격에있는 요소가 비교되고 교체됩니다.
A[0]> A[1]
→ 교체 됨,(1,3,4,6,5,7,9,8)
.
A[0] .. A[2]
→ 정렬 됨
A[0] .. A[3]
→ 정렬 됨
A[0] .. A[3]
→ 정렬되었지만 A[3]> A[4] → 교체 됨,(1,3,4,5,6,7,9,8)
.
A[0] .. A[5]
→ 정렬 됨
A[0] .. A[6]
→ 정렬 됨
A[0] .. A[6]
→ 정렬되었지만 A[6]> A[7] → 교체 됨,(1, 3, 4, 5, 6, 7, 8, 9)
.
Shell 정렬 알고리즘 구현
#include <bits/stdc++.h>
using namespace std;
void shellSort(int arr[], int n) {
for (int gap = n / 2; gap > 0; gap /= 2) {
for (int i = gap; i < n; i += 1) {
int temp = arr[i];
int j;
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap)
arr[j] = arr[j - gap];
arr[j] = temp;
}
}
}
int main() {
int n = 8;
int arr[8] = {9, 8, 3, 7, 5, 6, 4, 1};
cout << "Input arr: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << "\n";
shellSort(arr, n); // Sort elements in ascending order
cout << "Output arr: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << "\n";
}
Shell 정렬 알고리즘 복잡성
시간 복잡성
- 평균 사례
복잡성은 정렬을 위해 선택한 순서에 따라 다릅니다. 시간 복잡도는 [Big Theta] : O(nlog(n)2)의 순서입니다.
- 최악의 경우
Shell 정렬의 최악의 경우 시간 복잡도는 항상 O(n2)보다 작습니다. 더 정확하게 Poonen의 정리에 따르면 Θ(nlogn)2/(log log n)2) 또는 Θ(nlog n)2/log log n) 또는 Θ(n(log n)2) 또는 그 사이에 있습니다. 최악의 경우 시간 복잡도는 [Big O] : O(n2)보다 작습니다.
- 베스트 케이스
최상의 경우는 배열이 이미 정렬되어 있고 각 간격에 필요한 비교가 배열의 크기와 같을 때 발생합니다. 최적의 시간 복잡도는 [Big Omega] :O(nlogn)
입니다.
공간 복잡성
Shell 정렬 알고리즘의 공간 복잡성은 임시 변수 이외의 추가 메모리가 필요하지 않기 때문에O(n)
입니다.
Harshit Jindal has done his Bachelors in Computer Science Engineering(2021) from DTU. He has always been a problem solver and now turned that into his profession. Currently working at M365 Cloud Security team(Torus) on Cloud Security Services and Datacenter Buildout Automation.
LinkedIn