ALDS1_2_D シェルソートをC++で解いてみた[AIZU ONLINE JUDGE]

AIZU ONLINE JUDGE

こんにちは! mnbd(@mnbbbbbd)です。

AIZU ONLINE JUDGEの「ALDS1_2_D Shell Sort」を解いてみましたので、その回答と解説をご紹介いたします。

プログラミング初心者なので、もっといい回答があるに違いありません。

あくまでも「動作はする」サンプルとしてご覧ください。

問題文

次のプログラムは、挿入ソートを応用して n 個の整数を含む数列 A を昇順に整列するプログラムです。

1 insertionSort(A, n, g)
2 for i = g to n-1
3 v = A[i]
4 j = i - g
5 while j >= 0 && A[j] > v
6 A[j+g] = A[j]
7 j = j - g
8 cnt++
9 A[j+g] = v
10
11 shellSort(A, n)
12 cnt = 0
13 m = ?
14 G[] = {?, ?,..., ?}
15 for i = 0 to m-1
16 insertionSort(A, n, G[i])

shellSort(A, n) は、一定の間隔 g だけ離れた要素のみを対象とした挿入ソートである insertionSort(A, n, g) を、最初は大きい値から g を狭めながら繰り返します。これをシェルソートと言います。

上の疑似コードの ? を埋めてこのプログラムを完成させてください。n と数列 A が与えられるので、疑似コード中の m、m 個の整数 Gi(i=0,1,…,m−1)、入力 Aを昇順にした列を出力するプログラムを作成してください。ただし、出力は以下の条件を満 たす必要があります。

https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/2/ALDS1_2_D

解答

#include <bits/stdc++.h>
using namespace std;

void print(int a[], int n, int *cnt, vector<int> g) {
    cout << g.size() << endl;
    for(int i = g.size() - 1; i >= 0; i--) {
        cout << g[i] << (i == 0 ? '\n' : ' ');
    }
    cout << *cnt << endl;
    for(int i = 0; i < n; i++) {
        cout << a[i] << endl;
    }
}

void insertion_sort(int a[], int n, int h, int *cnt) {
    for(int i = h; i < n; i++) {
        int v = a[i];
        int j = i - h;
        while(j >= 0 && a[j] > v) {
            a[j + h] = a[j];
            j -= h;
            ++*cnt;
        }
        a[j + h] = v;
    }
}

void shell_sort(int a[], int n, int *cnt, vector<int> g) {
    *cnt = 0;
    int x = 1;
    while(x <= n) {
        g.push_back(x);
        x = 3 * x + 1;
    }
    int m = g.size();
    for(int i = m - 1; i >= 0; i--) {
        insertion_sort(a, n, g[i], cnt);
    }
}

int main() {
    int n;
    cin >> n;
    int a[n];
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
    int cnt = 0;
    vector<int> g;
    // print(a, n, &cnt);
    // insertion_sort(a, n, 1, &cnt);
    shell_sort(a, n, &cnt, g);
    print(a, n, &cnt, g);
    return 0;
}

感想

これは難しかったです。

特にシェルソートの理解のところ。

アルゴリズムの理解は、コードを見ただけではわからないなと改めて思います。

配列を出力したり、デバッガで確認しても、その流れがわからないというか…。

紙に図を書くなどして理解したいところですが、うまくいってません。

今回は、自力では解けずに一般解説もなかったため、他の方のコードを参考にさせていただきなら書きました。

まとめ

AIZU ONLINE JUDGEの「ALDS1_2_D Shell Sort」を解いてみましたので、その回答と解説をご紹介いたしました。

少しずつですが、プログラミングの勉強をしています。
まだ初心者ですが、よかったらつながっていただけると嬉しいです。
Twitterアカウント(@mnbbbbbd

以上です。
読んでいただきありがとうございました!