#include <iostream>
#include <cstdlib>
#include <ctime>
#define MAX 30
#define MAX1 100000
#define MAX2 500000
#define MAX3 1000000
#define MAX4 5000000
#define MAX5 10000000
using namespace std;
void shell_sort3h1(int a[], int n)
{ /* h = 3*h + 1 이용 */
int i, j, k, h, v;
for (h = 1; h < n; h = 3 * h + 1); /* n 보다 작은 h 의 최대값 가짐 */
for (; h > 0; h /= 3)// h의 값을 줄여가면서 계산
{
for (i = h; i <= n; i++) // 최대값 h가 n보다 작을 때까지 부분 배열
{
v = a[i];// v에 a[i]값 저장
j = i; // j는 인덱스를 기억
while(j >= h && a[j - h] > v) {
a[j] = a[j-h];
j = j - h;
}
a[j] = v;
}
}
}
void shell_sort3h(int a[], int n)
{ /* h = 3*h + 1 이용 */
int i, j, k, h, v;
for (h = 1; h < n; h = 3 * h); /* n 보다 작은 h 의 최대값 가짐 */
for (; h > 0; h /= 3)// h의 값을 줄여가면서 계산
{
for (i = h; i <= n; i++) // 최대값 h가 n보다 작을 때까지 부분 배열
{
v = a[i];// v에 a[i]값 저장
j = i; // j는 인덱스를 기억
while(j >= h && a[j - h] > v) {
a[j] = a[j-h];
j = j - h;
}
a[j] = v;
}
}
}
void shell_sort5h1(int a[], int n)
{ /* h = 3*h + 1 이용 */
int i, j, k, h, v;
for (h = 1; h < n; h = 5 * h + 1); /* n 보다 작은 h 의 최대값 가짐 */
for (; h > 0; h /= 5)// h의 값을 줄여가면서 계산
{
for (i = h; i <= n; i++) // 최대값 h가 n보다 작을 때까지 부분 배열
{
v = a[i];// v에 a[i]값 저장
j = i; // j는 인덱스를 기억
while(j >= h && a[j - h] > v) {
a[j] = a[j-h];
j = j - h;
}
a[j] = v;
}
}
}
void checkSort(int a[], int n){
int i, sorted;
sorted = 1;
for( i = 0; i < n; i ++) {
if(a[i] > a[i + 1]) {
sorted = 0;
}
if(!sorted) {
break;
}
}
if(sorted == 0) {
cout << "sort error" << endl;
}
else {
cout << "sort complete" << endl;
}
}
int main()
{
int n1 = MAX1;
int n2 = MAX2;
int n3 = MAX3;
int n4 = MAX4;
int n5 = MAX5;
int arr[n3];
clock_t start, finish, start1, finish1;
double duration, duration1;
for(int i = 0; i < n3; i++) {
arr[i] = rand() % n3;
}
start = clock();
shell_sort5h1(arr, n3);
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "increament : 5h + 1, decreament h/5 shell sort time(N = " << n3 << ") : " << duration <<"sec";
cout << '\n';
checkSort(arr, n3);
return 0;
}
전체 코드이다. shell sort는 한 배열을 여러 개의 부분 배열로 나누어 그 배열에 대해 insert sort 를 실행하는 정렬방법이다.
이 때 shell sort의 알고리즘을 살펴보면 다음과 같다.
1. shell sort
void shell_sort3h1(int a[], int n)
{ /* h = 3*h + 1 이용 */
int i, j, k, h, v;
for (h = 1; h < n; h = 3 * h + 1); /* n 보다 작은 h 의 최대값 가짐 */
for (; h > 0; h /= 3)// h의 값을 줄여가면서 계산
{
for (i = h; i <= n; i++) // 최대값 h가 n보다 작을 때까지 부분 배열
{
v = a[i];// v에 a[i]값 저장
j = i; // j는 인덱스를 기억
while(j >= h && a[j - h] > v) {
a[j] = a[j-h];
j = j - h;
}
a[j] = v;
}
}
}
h를 통해 전체 array개수보다는 작으면서 1부터 시작해 일정한 간격으로 index를 이동했을 때 가장 큰 h를 잡는다.
그 후 h를 h/3으로 줄여가면서 부분 배열에 대해 insertion sort를 수행하면 된다.
나는 shell sort의 데이터의 수에 따라 또한 증감식에 따라 시간을 측정해보았다.
1. 증가식 3h + 1, 감소식 h/3의 경우 n = 100000, 500000의 경우
N = 5000000의 경우이다.
N = 10000000
2. 증가식 3h , 감소식 h/3의 경우
N = 100000, 500000의 경우
N = 1000000의 경우
N = 5000000의 경우
N = 10000000의 경우
1. 증가식 5h+1, 감소식 h/5의 경우
N = 100000, 500000일 경우
N = 1000000
N = 5000000
N = 10000000
구현을 하고 시간을 측정해본 결과 증가식이 3h + 1인 경우에 가장 빠른 시간이 측정되었다. 수학적으로 증명은 하지 못하겠으나 구글링을 통해 본 결과에서도 3h+1이 가장 보편적으로 사용되는 증가식이라고 한다.
'c++ > 알고리즘' 카테고리의 다른 글
백준-1012번 - 유기농 배추 (0) | 2022.03.29 |
---|---|
백준2178번-미로BFS (0) | 2022.03.28 |
백준 9996 (0) | 2022.03.19 |
백준 1159 (0) | 2022.03.18 |
c++ 행렬 곱셈 (0) | 2022.03.16 |
댓글