アルゴリズムとデータ構造:コームソート

コームソートは離れた要素を比較・交換して
徐々に距離(ギャップ)を縮めて行く。
荒い目から細かい目ですいていくように
髪をとかすコームが名前の由来らしい。


[計算量]
なぜか本に書いてない。
wikiには『実行速度は、ほぼO(n log n)』とありますが。。。あとで調べる。


[comb_sort.c]

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 10 /* データ件数 */

int sort[N];
int count;
void CombSort(void);
void output(int list[]);

void CombSort(void){

    int i, temp, flag, gap;
    gap = N;

    do {
        gap = (gap * 10) / 13; 
        if(gap == 0){
            gap = 1;
        }

        flag = 1;

        printf("gap:%d\n",gap);
        for(i = 0; i < N - gap; i++){
            printf("sort[%d]:%d > sort[%d]:%d\n",i,sort[i], i+gap, sort[i+gap]);
            if(sort[i] > sort[i+gap]){
                flag = 0;
                temp = sort[i];
                sort[i] = sort[i+gap];
                sort[i+gap] = temp;

                output(sort);
            } 
            ++count;
        }
    } while((gap > 1) || flag != 1);
}

int main(void){
    int i;
    clock_t start,end;
    srand((unsigned int) time(NULL));
    printf("Stundy...\n");
    for(i = 0; i < N; i++){
        sort[i]  = rand() % 10 + 1;
    }
    output(sort);

    printf("<< Start!! >>\n");
    start = clock();
    CombSort();
    end = clock();
    printf("<< End!! >>\n");
    printf("Count:%d\n",count);
    printf("Time:%.2f\n",(double)(end-start)/CLOCKS_PER_SEC);

    return EXIT_SUCCESS;
}

void output(int list[]){
    int i=0;
    printf("sort => [");
    while(1){
        printf("%d",list[i]); 
        ++i;
        if(list[i] == '\0') break;
        else printf(",");
    }
    printf("]\n");
}

データ10件で実行したときのログ

[dela@www20328u sort]$ ./comb_sort
Stundy...
sort => [4,5,9,5,6,9,9,2,8,6]
<< Start!! >>
gap:7
sort[0]:4 > sort[7]:2
sort => [2,5,9,5,6,9,9,4,8,6]
sort[1]:5 > sort[8]:8
sort[2]:9 > sort[9]:6
sort => [2,5,6,5,6,9,9,4,8,9]
gap:5
sort[0]:2 > sort[5]:9
sort[1]:5 > sort[6]:9
sort[2]:6 > sort[7]:4
sort => [2,5,4,5,6,9,9,6,8,9]
sort[3]:5 > sort[8]:8
sort[4]:6 > sort[9]:9
gap:3
sort[0]:2 > sort[3]:5
sort[1]:5 > sort[4]:6
sort[2]:4 > sort[5]:9
sort[3]:5 > sort[6]:9
sort[4]:6 > sort[7]:6
sort[5]:9 > sort[8]:8
sort => [2,5,4,5,6,8,9,6,9,9]
sort[6]:9 > sort[9]:9
gap:2
sort[0]:2 > sort[2]:4
sort[1]:5 > sort[3]:5
sort[2]:4 > sort[4]:6
sort[3]:5 > sort[5]:8
sort[4]:6 > sort[6]:9
sort[5]:8 > sort[7]:6
sort => [2,5,4,5,6,6,9,8,9,9]
sort[6]:9 > sort[8]:9
sort[7]:8 > sort[9]:9
gap:1
sort[0]:2 > sort[1]:5
sort[1]:5 > sort[2]:4
sort => [2,4,5,5,6,6,9,8,9,9]
sort[2]:5 > sort[3]:5
sort[3]:5 > sort[4]:6
sort[4]:6 > sort[5]:6
sort[5]:6 > sort[6]:9
sort[6]:9 > sort[7]:8
sort => [2,4,5,5,6,6,8,9,9,9]
sort[7]:9 > sort[8]:9
sort[8]:9 > sort[9]:9
gap:1
sort[0]:2 > sort[1]:4
sort[1]:4 > sort[2]:5
sort[2]:5 > sort[3]:5
sort[3]:5 > sort[4]:6
sort[4]:6 > sort[5]:6
sort[5]:6 > sort[6]:8
sort[6]:8 > sort[7]:9
sort[7]:9 > sort[8]:9
sort[8]:9 > sort[9]:9
<< End!! >>
Count:41
Time:0.00
[dela@www20328u sort]$ ./comb_sort
Stundy...
sort => [4,5,9,5,6,9,9,2,8,6]
<< Start!! >>
gap:7
sort[0]:4 > sort[7]:2
sort => [2,5,9,5,6,9,9,4,8,6]
sort[1]:5 > sort[8]:8
sort[2]:9 > sort[9]:6
sort => [2,5,6,5,6,9,9,4,8,9]
gap:5
sort[0]:2 > sort[5]:9
sort[1]:5 > sort[6]:9
sort[2]:6 > sort[7]:4
sort => [2,5,4,5,6,9,9,6,8,9]
sort[3]:5 > sort[8]:8
sort[4]:6 > sort[9]:9
gap:3
sort[0]:2 > sort[3]:5
sort[1]:5 > sort[4]:6
sort[2]:4 > sort[5]:9
sort[3]:5 > sort[6]:9
sort[4]:6 > sort[7]:6
sort[5]:9 > sort[8]:8
sort => [2,5,4,5,6,8,9,6,9,9]
sort[6]:9 > sort[9]:9
gap:2
sort[0]:2 > sort[2]:4
sort[1]:5 > sort[3]:5
sort[2]:4 > sort[4]:6
sort[3]:5 > sort[5]:8
sort[4]:6 > sort[6]:9
sort[5]:8 > sort[7]:6
sort => [2,5,4,5,6,6,9,8,9,9]
sort[6]:9 > sort[8]:9
sort[7]:8 > sort[9]:9
gap:1
sort[0]:2 > sort[1]:5
sort[1]:5 > sort[2]:4
sort => [2,4,5,5,6,6,9,8,9,9]
sort[2]:5 > sort[3]:5
sort[3]:5 > sort[4]:6
sort[4]:6 > sort[5]:6
sort[5]:6 > sort[6]:9
sort[6]:9 > sort[7]:8
sort => [2,4,5,5,6,6,8,9,9,9]
sort[7]:9 > sort[8]:9
sort[8]:9 > sort[9]:9
gap:1
sort[0]:2 > sort[1]:4
sort[1]:4 > sort[2]:5
sort[2]:5 > sort[3]:5
sort[3]:5 > sort[4]:6
sort[4]:6 > sort[5]:6
sort[5]:6 > sort[6]:8
sort[6]:8 > sort[7]:9
sort[7]:9 > sort[8]:9
sort[8]:9 > sort[9]:9
<< End!! >>
Count:41
Time:0.00

データ1万件の結果

Stundy...
<< Start!! >>
<< End!! >>
Count:286738
Time:0.00

データ100万件の結果

Stundy...
<< Start!! >>
<< End!! >>
Count:46666765
Time:0.26

データ1億件の結果

Stundy...
<< Start!! >>
<< End!! >>
Count:-2023267793
Time:33.89

速い。
コームソート、クイックソートは不安定ソート。
マージソートは安定ソート。


[安定ソート]

  • 同等の値があった場合、それらの入れ替えが発生しない。
  • 同等なデータのソート前の順序が、ソート後も保存される。
  • ソート途中の各状態において、常に順位の位置関係を保っている。


[不安定ソート]

  • 同等の値があった場合、それらの入れ替えが発生する可能性がある。

例は名と姓でソートする場合に、通常は姓でソートした後に名でソートする。
同じ姓があった場合、名の方でも五十音順にソートできている。不安定ソートは五十音順に並ばない。


[内部ソート]
ソートされるデータの格納領域を変更して処理を進めていくIn-placeのソート


[外部ソート]
ソートされるデータの格納領域以外に O(n) 以上の一時的な記憶領域が必要であるソートを外部ソート

コームソート、クイックソートは内部ソート
マージソートは外部ソート