コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

「シェーカーソート」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
関連Commons。
Cewbot (会話 | 投稿記録)
m Bot作業依頼: sourceタグをsyntaxhighlightタグに置換 (Category:非推奨のsourceタグを使用しているページ) - log
17行目: 17行目:
===実装例===
===実装例===
[[C++]]言語による実装例を示す。
[[C++]]言語による実装例を示す。
<source lang="cpp">
<syntaxhighlight lang="cpp">
#include <algorithm> // std::swap
#include <algorithm> // std::swap


62行目: 62行目:
}
}
}
}
</syntaxhighlight>
</source>


===動作例===
===動作例===

2020年7月5日 (日) 22:46時点における版

シェーカーソート
視覚化したシェーカーソート
クラス ソート
データ構造 配列
最悪計算時間 О(n²)

シェーカーソート (: shaker sort) は、ソートアルゴリズムの一つ。バブルソートを、効率がよくなるように改良したもの。別名は、双方向バブルソート改良交換法[1]

バブルソートではスキャンを一方向にしか行わないのに対し、シェーカーソートでは交互に二方向に行う。バブルソートと同じく安定な内部ソートで、最悪の場合の時間計算量O(n2)である。

アルゴリズム

バブルソートで1回スキャンを行うと、最後の要素1個がスキャン範囲中最大であることが分かり次回のスキャン範囲を1狭めることができる。さらに、このスキャンの最後で連続してm個の要素の交換が行われていなければ、そのm個についてはソート済みであることが分かるので、次回のスキャン範囲をm狭めることができる。この工夫で、後半が殆ど整列済みのデータに対してバブルソートが高速に行えるようになる。

シェーカーソートはこれに加え、スキャン方向を毎回反転することにより、スキャン範囲を後方からだけではなく前方からも狭めるようにしたものである。挿入ソートのように、殆ど整列済みのデータに対しては高速に行うことができる。

実装例

C++言語による実装例を示す。

#include <algorithm> // std::swap

template<typename T> void shaker_sort(T data[], int num_elements)
{
    int top_index = 0;
    int bot_index = num_elements - 1;

    while (true)
    {
        int last_swap_index;

        /* 順方向のスキャン */
        last_swap_index = top_index;

        for (int i = top_index; i < bot_index; i++)
        {
            if (data[i] > data[i+1])
            {
                std::swap(data[i], data[i+1]);
                last_swap_index = i;
            }
        }
        bot_index = last_swap_index; /* 後方のスキャン範囲を狭める */

        if (top_index == bot_index)
            break;

        /* 逆方向のスキャン */
        last_swap_index = bot_index;

        for (int i = bot_index; i > top_index; i--)
        {
            if (data[i] < data[i-1])
            {
                std::swap(data[i], data[i-1]);
                last_swap_index = i;
            }
        }
        top_index = last_swap_index; /* 前方のスキャン範囲を狭める */

        if (top_index == bot_index)
            break;
    }
}

動作例

t はスキャン範囲の先頭、b は末尾を表す。

初期データ: 8 4 3 7 6 5 2 1

1回目のスキャン終了後: (交換回数:7)

4 3 7 6 5 2 1 8
t           b

2回目のスキャン終了後: (交換回数:6)

1 4 3 7 6 5 2 8
  t         b

3回目のスキャン終了後: (交換回数:4)

1 3 4 6 5 2 7 8
  t       b

4回目のスキャン終了後: (交換回数:4)

1 2 3 4 6 5 7 8
    t     b

5回目のスキャン終了後: (交換回数:1)

1 2 3 4 5 6 7 8
    t   b

6回目のスキャン終了後: (交換回数:0)

1 2 3 4 5 6 7 8

合計交換回数:7+6+4+4+1+0=22 (バブルソートの場合22)

脚注

注釈
出典
  1. ^ シェーカーソートの意味(出典:デジタル大辞泉) - goo辞書

関連項目