45
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ソートアルゴリズム20種をCで作ってみた

Last updated at Posted at 2017-10-04

##実装したアルゴリズムたちの紹介

  • 教科書でしかみない バブルソート
  • バブルより効率が悪い ストゥージソート
  • さらに効率が悪い スローソート
  • 並列化していないバブルと同じ効率の悪い 奇偶転置ソート
  • バブルよりマシで不安定な 選択ソート
  • バブルよりマシで安定な 挿入ソート
  • 挿入ソートとよく似ている ノームソート
  • 挿入ソートの改良版な シェルソート
  • バブルにシェルと同様の改造が施した コムソート
  • タダの二本に枝分かれしていく木で作られた ツリーソート
  • ツリーと選択が融合した ヒープソート
  • ヒープソートの亜種な スムースソート
  • 同じくヒープソートの亜種な デカルト木ソート
  • 行ったり来たりな シェーカーソート
  • 分類上は選択ソートの仲間な サイクルソート
  • ある程度早い マージソート
  • 大量なソートでは早い 基数ソート
  • 基数と挿入の合わせ技 Proxmap sort
  • インプレースな基数ソート アメリカンフラッグソート
  • もっとも有名な クイックソート

##コード
####バブルソート

int bubble_sort(double *data,int size)
{
    int i,j,k;
    double tmp;
    
    i = size - 1;
    j = -1;
    while(i && j) {
        j = 0;
        for(k=0;k<i;k++) {
            if(data[k] > data[k+1]) {
                tmp = data[k+1];
                data[k+1] = data[k];
                data[k] = tmp;
                j = -1;
            }
        }
        i--;
    }
    
    return 0;
}

####ストゥージソート

void stooge_sort(double *data,int size)
{
    int i;
    double tmp;
    if(size > 1 && data[0] > data[size-1]) {
        tmp = data[0];
        data[0] = data[size-1];
        data[size-1] = tmp;
    }
    if(size >= 3) {
        i = (2*size + 2)/3;
        stooge_sort(data,i);
        stooge_sort(data + size - i,i);
        stooge_sort(data,i);
    }
    return;
}

####スローソート

void slow_sort(double *data,int size)
{
    int i;
    double tmp;
    if(size < 2) {
        return;
    }
    i = (size-1)/2;
    slow_sort(data,i+1);
    slow_sort(data+i+1,size-i-1);
    if(data[size-1] < data[i]) {
        tmp = data[i];
        data[i] = data[size-1];
        data[size-1] = tmp;
    }
    slow_sort(data,size-1);
    
    return;
}

####奇偶転置ソート

void odd_even_sort(double *data,int size)
{
    int i,j;
    double tmp;
    
    j=-1;
    while(j) {
        j=0;
        for(i=0;i+1<size;i+=2) {
            if(data[i] > data[i+1]) {
                tmp = data[i];
                data[i] = data[i+1];
                data[i+1] = tmp;
                j=-1;
            }
        }
        for(i=1;i+1<size;i+=2) {
            if(data[i] > data[i+1]) {
                tmp = data[i];
                data[i] = data[i+1];
                data[i+1] = tmp;
                j=-1;
            }
        }
    }
    
    return;
}

####選択ソート

void selection_sort(double *data,int size)
{
    int i,j,k;
    double tmp;
    for(i=0;i<size-1;i++) {
        tmp = data[i];
        k=i;
        for(j=i+1;j<size;j++) {
            if(tmp > data[j]) {
                tmp = data[j];
                k=j;
            }
        }
        if(k != i) {
            data[k] = data[i];
            data[i] = tmp;
        }
    }
    return;
}

####挿入ソート

void insertion_sort(double *data,int size)
{
    int i,j;
    double tmp;
    for(i=1;i<size;i++) {
        tmp=data[i];
        for(j=i;j>0 && data[j-1]>tmp;j--) 
            data[j]=data[j-1];
        data[j] = tmp;
    }
}

####ノームソート

void gnome_sort(double *data,int size)
{
    int i;
    double tmp;
    
    i=0;
    while(i<size-1)
    {
        if(data[i] > data[i+1]) {
            tmp = data[i];
            data[i] = data[i+1];
            data[i+1] = tmp;
            if(i) {
                i--;
            }
        } else {
            i++;
        }
    }
    
    return;
}

####シェルソート

int shell_sort(double *data,int size)
{
    int i,j,k;
    int *a,ret_code;
    double tmp;
    
    ret_code = 0;
    if(size <= 0) {
        ret_code = -1;
        goto error;
    }
    i=0;
    j=1;
    while(j<size) {
        k = j;
        while(k<size) {
            i++;
            k *= 3;
        }
        j *= 2;
    }
    if((a=(int *)malloc((i+2)*sizeof(int)))==NULL) {
        ret_code = -1;
        goto error;
    }
    a+=2;
    i=0;
    j=1;
    while(j<size) {
        k = j;
        while(k<size) {
            a[i++] = k;
            k *= 3;
        }
        j *= 2;
    }
    a[-2]=i;
    for(i=1;i<a[-2];i++) {
        j=i;
        while(j>0) {
            k=(j-1)>>1;
            if(a[j] > a[k]) {
                a[-1] = a[j];
                a[j] = a[k];
                a[k] = a[-1];
            } else {
                break;
            }
        }
    }
    for(i=a[-2]-1;i>0;i--) {
        a[-1] = a[i];
        a[i] = a[0];
        a[0] = a[-1];
        j=0;
        while(j*2+1<i) {
            k=j*2+1;
            if(k+1 < i && a[k] < a[k+1]) {
                k++;
            }
            if(a[j] < a[k]) {
                a[-1]=a[k];
                a[k] = a[j];
                a[j] = a[-1];
                j=k;
            } else {
                break;
            }
        }
    }
    for(i=a[-2]-1;i>=0;i--) {
        for(j=1;j<size;j++) {
            tmp = data[j];
            for(k=j;k-a[i]>=0 && data[k-a[i]]>tmp;k-=a[i]) {
                data[k] = data[k-a[i]];
            }
            data[k] = tmp;
        }
    }
    
    free(a-2);
    error:
    return ret_code;
}

####コムソート

void comb_sort(double *data,int size)
{
    int i,j,k;
    double tmp;
    
    j=size;
    k=-1;
    while(k) {
        j=(10*j)/13;
        if(j <= 1) {
            j = 1;
            k = 0;
        }
        for(i=0;i+j<size;i++) {
            if(data[i] > data[i+j]) {
                tmp = data[i];
                data[i] = data[i+j];
                data[i+j] = tmp;
                k=-1;
            }
        }
    }
    
    return;
}

####ツリーソート

int tree_sort(double *data,int size)
{
    int i,j,k,l,ret_code;
    double *a;
    int *b;
    ret_code = 0;
    if((a = (double *)malloc(size*sizeof(double))) == NULL) {
        ret_code = -1;
        goto error01;
    }
    if((b = (int *)malloc(3*size*sizeof(int))) == NULL) {
        ret_code = -1;
        goto error02;
    }
    
    for(i=0;i<3*size;i++) {
        b[i] = -1;
    }
    
    a[0] = data[0];
    for(i=1;i<size;i++) {
        j = 0;
        while(j >= 0) {
            if(a[j] > data[i]) {
                l = 1;
            } else {
                l = 2;
            }
            k = j;
            j = b[j*3 + l];
        }
        b[k*3 + l] = i;
        b[i*3 + 0] = k;
        a[i] = data[i];
    }
    
    i = 0;
    j = -1;
    k = 0;
    while(i != -1) {
        if(b[i*3 + 1] != -1 && j == b[i*3 + 0]) {
            j = i;
            i = b[i*3 + 1];
        } else if(b[i*3 + 2] != -1 && j != b[i*3 + 2]) {
            data[k++] = a[i];
            j = i;
            i = b[i*3 + 2];
        } else {
            if(j != b[i*3 + 2] || (b[i*3+1] == -1 && b[i*3+2] == -1)) {
                data[k++] = a[i];
            }
            j = i;
            i = b[i*3 + 0];
        }
    }
    
    free(b);
    error02:
    free(a);
    error01:
    return ret_code;
}

####ヒープソート

void heap_sort(double *data,int size)
{
    int i,j,k;
    double tmp;
    
    for(i=1;i<size;i++) {
        j = i;
        while(j>0) {
            k = (j-1)/2;
            if(data[k] < data[j]) {
                tmp = data[j];
                data[j] = data[k];
                data[k] = tmp;
                j = k;
            } else {
                break;
            }
        }
    }
    for(i=size-1;i>=0;i--) {
        tmp = data[i];
        data[i] = data[0];
        data[0] = tmp;
        j = 0;
        while(1) {
            if(2*j + 1 >= i) {
                break;
            }
            k = 2*j + 1;
            if(k+1 < i && data[k] < data[k+1]) {
                k++;
            }
            if(data[k] > data[j]) {
                tmp = data[j];
                data[j] = data[k];
                data[k] = tmp;
                j=k;
            } else {
                break;
            }
        }
    }
    return;
}

####スムースソート

void repair_tree(double *tree,int tree_size,unsigned int *leonardo_number)
{
    int i;
    double tmp;
    
    if(tree_size < 3) {
        return;
    }
    i=1;
    while(leonardo_number[i] < tree_size) i++;
    if(tree[leonardo_number[i-1]-1] < tree[tree_size-2]) {
        if(tree[tree_size-1] < tree[tree_size-2]) {
            tmp = tree[tree_size-2];
            tree[tree_size-2] = tree[tree_size-1];
            tree[tree_size-1] = tmp;
            repair_tree(tree + leonardo_number[i-1],leonardo_number[i-2],leonardo_number);
        }
    } else {
        if(tree[tree_size-1] < tree[leonardo_number[i-1]-1]) {
            tmp = tree[leonardo_number[i-1]-1];
            tree[leonardo_number[i-1]-1] = tree[tree_size-1];
            tree[tree_size-1] = tmp;
            repair_tree(tree,leonardo_number[i-1],leonardo_number);
        }
    }
    
    return;
}

int smooth_sort(double *data,int size)
{
    int i,j,k,ret_code;
    unsigned int *leonardo_number;
    int *tree_size,*tree_offset;
    double tmp;
    ret_code = 0;
    
    if(size < 1) {
        ret_code = -1;
        goto error01;
    }
    if((leonardo_number=(unsigned int *)malloc(3*64*sizeof(unsigned int)))==NULL) {
        ret_code = -1;
        goto error01;
    }
    tree_size = (int *)(leonardo_number + 64);
    tree_offset = tree_size + 64;
    leonardo_number[0] = 1;
    leonardo_number[1] = 1;
    i=2;
    while(i<45) {
        leonardo_number[i] = leonardo_number[i-1] + leonardo_number[i-2] + 1;
        i++;
    }
    while(i<3*64) {
        leonardo_number[i++] = 0;
    }
    
    tree_offset[0] = 0;
    for(i=0;i<size;i++) {
        j = 0;
        while(tree_size[j]) j++;
        tree_size[j]++;
        k=0;
        while(j>=2) {
            while(leonardo_number[k] < tree_size[j] + tree_size[j-1] + tree_size[j-2]) k++;
            if(leonardo_number[k] == tree_size[j] + tree_size[j-1] + tree_size[j-2]) {
                tree_size[j] = 0;
                tree_size[j-1] = 0;
                tree_size[j-2] = leonardo_number[k];
                j-=2;
            } else {
                j--;
            }
        }
        j=0;
        while(tree_size[j]) {
            tree_offset[j+1] = tree_offset[j] + tree_size[j];
            j++;
        }
        if(j >= 1) {
            repair_tree(data+tree_offset[j-1],tree_size[j-1],leonardo_number);
        }
    }
    j=1;
    k=0;
    while(tree_size[j]) {
        if(data[tree_offset[j+1]-1] > data[tree_offset[k+1]-1]) {
            k = j;
        }
        j++;
    }
    if(j != k+1) {
        tmp = data[tree_offset[j]-1];
        data[tree_offset[j]-1] = data[tree_offset[k+1]-1];
        data[tree_offset[k+1]-1] = tmp;
        repair_tree(data+tree_offset[j-1],tree_size[j-1],leonardo_number);
    }
    
    while(1) {
        j = 0;
        i = 0;
        while(tree_size[j]) {
            i += tree_size[j];
            j++;
        }
        if(i <= 1) break; 
        j--;
        i = 0;
        while(leonardo_number[i] < tree_size[j]) i++;
        if(i >= 2) {
            tree_size[j] = leonardo_number[i-1];
            tree_size[j+1] = leonardo_number[i-2];
        } else {
            tree_size[j]--;
        }
        j=0;
        k=0;
        while(tree_size[j]) {
            tree_offset[j+1] = tree_offset[j] + tree_size[j];
            if(data[tree_offset[j+1]-1] > data[tree_offset[k+1]-1]) {
                k = j;
            }
            j++;
        }
        if(j != k+1) {
            tmp = data[tree_offset[j]-1];
            data[tree_offset[j]-1] = data[tree_offset[k+1]-1];
            data[tree_offset[k+1]-1] = tmp;
        }
        j=0;
        while(tree_size[j]) {
            repair_tree(data+tree_offset[j],tree_size[j],leonardo_number);
            j++;
        }
    }
    
    free(leonardo_number);
    error01:
    return ret_code;
}

####デカルト木ソート

int cartesian_tree_sort(double *data,int size)
{
    int i,j,k,l,ret_code;
    double *a;
    int *b,*c;
    ret_code = 0;
    
    i = ((3 * size * sizeof(int) + sizeof(int) -1)/sizeof(double))*sizeof(double);
    j = (i + sizeof(int) - 1)/sizeof(int);
    if((a=(double *)malloc((j + size) * sizeof(int)))==NULL) {
        ret_code = -1;
        goto error01;
    }
    b = (int *)a;
    c = b + j;
    
    for(i=0;i<4*size;i++) {
        b[i] = -1;
    }
    k=0;
    for(i=1;i<size;i++) {
        j = i-1;
        while(b[3*j] != -1 && data[j] > data[i]) j=b[3*j];
        if(data[j] > data[i]) {
            k=i;
            b[3*j] = i;
            b[3*i+1] = j;
        } else if(b[3*j+2] == -1) {
            b[3*j+2] = i;
            b[3*i] = j;
        } else {
            b[3*i] = j;
            b[3*i+1] = b[3*j+2];
            b[3*b[3*j+2]] = i;
            b[3*j+2] = i;
        }
    }
    i=0;
    j=1;
    c[i] = k;
    while(i < size && c[i] != -1) {
        k = b[3*c[i]+1];
        if(k != -1) {
            for(l=j;data[k] < data[c[l-1]];l--) {
                c[l] = c[l-1];
            }
            c[l] = k;
            j++;
        }
        k = b[3*c[i]+2];
        if(k != -1) {
            for(l=j;data[k] < data[c[l-1]];l--) {
                c[l] = c[l-1];
            }
            c[l] = k;
            j++;
        }
        i++;
    }
    for(i=0;i<size;i++) {
        a[i] = data[i];
    }
    for(i=0;i<size;i++) {
        data[i] = a[c[i]];
    }
    
    free(a);
    error01:
    return ret_code;
}

####シェーカーソート

void cocktail_shaker_sort(double *data,int size)
{
    int i,j,k,l;
    double tmp;
    
    i=0;
    j=size-1;
    l=-1;
    while(l) {
        l=0;
        for(k=i;k<j;k++) {
            if(data[k] > data[k+1]) {
                tmp = data[k];
                data[k] = data[k+1];
                data[k+1] = tmp;
                l=-1;
            }
        }
        j--;
        if(!l) {
            break;
        }
        l=0;
        for(k=j;k>i;k--) {
            if(data[k] < data[k-1]) {
                tmp = data[k];
                data[k] = data[k-1];
                data[k-1] = tmp;
                l=-1;
            }
        }
        i++;
    }
    return;
}

####サイクルソート

void cycle_sort(double *data,int size)
{
    int i,j,k;
    double tmp;
    
    i = 0;
    while(i<size-1) {
        tmp = data[i];
        k=0;
        j=i+1;
        while(j<size) {
            if(tmp > data[j++]) k++;
        }
        if(k) {
            data[i] = data[i+k];
            data[i+k] = tmp;
        } else {
            i++;
        }
    }
    
    return;
}

####マージソート(再帰版)

void merge_sort_c(double *a,double *b,int n,int m) {
    int i,j,k,l;
    double *c;
    k = n >> 1;
    if(n > 2) {
        j = n - k;
        merge_sort_c(a,b,k,m^0x01);
        merge_sort_c(a+k,b+k,j,m^0x01);
    } else if(m == 0) {
        for(i=0;i<n;i++) {
            b[i] = a[i];
        }
    }
    if(m != 0) {
        c = a;
        a = b;
        b = c;
    }
    i = 0;
    j = k;
    l = 0;
    while(i<k && j<n) {
        if(b[i] <= b[j]) {
            a[l++] = b[i++];
        } else {
            a[l++] = b[j++];
        }
    }
    while(i<k) {
        a[l++] = b[i++];
    }
    while(j<n) {
        a[l++] = b[j++];
    }
}

int merge_sort(double *data,int size) {
    double *tmp;
    if((tmp = (double *)malloc(size*sizeof(double))) == NULL) {
        return -1;
    }
    merge_sort_c(data,tmp,size,0);
    free(tmp);
    return 0;
}

####マージソート(非再帰版)

int merge_sort(double *data,int size)
{
    int i,j,k,l,m,n,m_max,n_max,ret_code;
    double *tmp[2];
    ret_code = 0;
    
    tmp[0] = data;
    if((tmp[1] = (double *)malloc(size*sizeof(double))) == NULL) {
        ret_code = -1;
        goto error01;
    }
    
    l = 0x00;
    for(i=1;i<size;i*=2) {
        for(j=0;j<size;j+=i*2) {
            k = j;
            m = j;
            n = j + i;
            m_max = (m+i < size)? m+i : size;
            n_max = (n+i < size)? n+i : size;
            while(m<m_max && n<n_max) {
                if(tmp[l][m] <= tmp[l][n]) {
                    tmp[l^0x01][k++] = tmp[l][m++];
                } else {
                    tmp[l^0x01][k++] = tmp[l][n++];
                }
            }
            while(m<m_max) {
                tmp[l^0x01][k++] = tmp[l][m++];
            }
            while(n<n_max) {
                tmp[l^0x01][k++] = tmp[l][n++];
            }
        }
        l ^= 0x01;
    }
    
    if(l == 0x01) {
        for(i=0;i<size;i++) {
            tmp[0][i] = tmp[1][i];
        }
    }
    
    free(tmp[1]);
    error01:
    return ret_code;
}

####基数ソート

int radix_sort(double *data,int size)
{
    int i,j,k,ret_code;
    double **a;
    int **b;
    unsigned char *c;
    ret_code = 0;
    
    if(size <= 1) {
        ret_code = -1;
        goto error;
    }
    i = 2*sizeof(double *);
    i = ((i + sizeof(int *) - 1)/sizeof(int *));
    i = (i +sizeof(double))*sizeof(int *);
    i = ((i + sizeof(int) - 1)/sizeof(int));
    i = (i + 257*sizeof(double))* sizeof(int);
    i = ((i + sizeof(double) - 1)/sizeof(double));
    i = (i+size) * sizeof(double);
    if((a=(double **)malloc(i))==NULL) {
        ret_code = -1;
        goto error;
    }
    i    = 2*sizeof(double *);
    i    = ((i + sizeof(int *) - 1)/sizeof(int *));
    b    = ((int **)a) + i;
    i    = (i +sizeof(double))*sizeof(int *);
    i    = ((i + sizeof(int) - 1)/sizeof(int));
    b[0] = ((int *)a) + i;
    i    = (i + 257*sizeof(double))* sizeof(int);
    i    = ((i + sizeof(double) - 1)/sizeof(double));
    a[1] = ((double *)a) + i;
    a[0] = data;
    for(i=1;i<sizeof(double);i++) {
        b[i] = b[i-1] + 257;
    }
    
    for(i=0;i<257*sizeof(double);i++) {
        b[0][i] = 0;
    }
    for(i=0;i<size;i++) {
        c = (unsigned char *)(data + i);
        if(c[sizeof(double)-1]&0x80) {
            for(j=0;j<sizeof(double);j++) {
                c[j] = ~c[j];
            }
        } else {
            c[sizeof(double)-1] ^= 0x80;
        }
        for(j=0;j<sizeof(double);j++) {
            b[j][1+c[j]]++;
        }
    }
    
    k = 0x00;
    for(i=0;i<sizeof(double);i++) {
        for(j=0;j<256;j++) {
            b[i][j+1] += b[i][j];
        }
        for(j=0;j<size;j++) {
            c = (unsigned char *)(a[k] + j);
            a[k^0x01][b[i][c[i]]] = a[k][j];
            b[i][c[i]]++;
        }
        k ^= 0x01;
    }
    if(k==0x01) {
        for(i=0;i<size;i++) {
            data[i] = a[1][i];
        }
    }
    
    for(i=0;i<size;i++) {
        c = (unsigned char *)(data + i);
        if(c[sizeof(double)-1]&0x80) {
            c[sizeof(double)-1] ^= 0x80;
        } else {
            for(j=0;j<sizeof(double);j++) {
                c[j] = ~c[j];
            }
        }
    }
    
    free(a);
    error:
    return ret_code;
}

####Proxmap sort

unsigned int mapkey(double a)
{
    uint64_t *b = (uint64_t *)&a;
    *b = *b >> 52;
    if((*b)&0x800) {
        *b ^= 0xfff;
    } else {
        *b ^= 0x800;
    }
    return (unsigned int)*b;
}

int proxmap_sort(double *data,int size)
{
    int i,j,k,ret_code;
    double *a;
    unsigned int *b,*c;
    ret_code = 0;
    k = (key_length > size)? key_length : size;
    i = (((size + k)*sizeof(unsigned int) + sizeof(double) - 1)/sizeof(double))*sizeof(double);
    j = i/sizeof(unsigned int);
    i += size * sizeof(double);
    if((b=(unsigned int *)malloc(i))==NULL) {
        ret_code = -1;
        goto error01;
    }
    c = b + k;
    a = (double *)(b + j);
    
    for(i=0;i<key_length;i++) {
        b[i] = 0;
    }
    for(i=0;i<size;i++) {
        c[i] = mapkey(data[i]);
        b[c[i]]++;
    }
    j = 0;
    for(i=0;i<key_length;i++) {
        k = b[i];
        b[i] = j;
        j += k;
    }
    for(i=0;i<size;i++) {
        c[i] = b[c[i]];
    }
    for(i=0;i<size;i++) {
        b[i] = 0;
    }
    for(i=0;i<size;i++) {
        j = c[i];
        while(b[j] && data[i] >= a[j]) j++;
        if(!b[j]) {
            b[j] = -1;
            a[j] = data[i];
        } else {
            k = j + 1;
            while(b[k]) k++;
            b[k] = -1;
            while(k > j) {
                a[k] = a[k-1];
                k--;
            }
            a[j] = data[i];
        }
    }
    for(i=0;i<size;i++) {
        data[i] = a[i];
    }
    
    free(b);
    error01:
    return ret_code;
}

####アメリカンフラッグソート(再帰版)

void american_flag_sort_c(double *data,int size,int **a,int l)
{
    int i,j;
    unsigned char *b;
    double tmp;
    if(l==0|| size < 1) {
        return;
    }
    l--;
    for(i=0;i<257;i++) {
        a[l][i] = 0;
    }
    for(i=0;i<size;i++) {
        b = (unsigned char *)(data + i);
        a[l][1+b[l]]++;
    }
    for(i=0;i<256;i++) {
        a[l][i+1] += a[l][i];
        a[sizeof(double)][i] = a[l][i+1];
    }
    b = (unsigned char *)&tmp;
    for(i=0;i<256;i++) {
        for(j=a[l][i];j<a[sizeof(double)][i];) {
            tmp = data[j];
            if(b[l] != i) {
                data[j] = data[a[l][b[l]]];
                data[a[l][b[l]]] = tmp;
            } else {
                j++;
            }
            a[l][b[l]]++;
        }
    }
    a[l][0] = 0;
    for(i=0;i<256;i++) {
        a[l][i+1] = a[sizeof(double)][i];
    }
    for(i=0;i<256;i++) {
        american_flag_sort_c(data+a[l][i],a[l][i+1]-a[l][i],a,l);
    }
    
    return;
}

int american_flag_sort(double *data,int size)
{
    int i,j,ret_code;
    int *a[1+sizeof(double)];
    unsigned char *b;
    ret_code = 0;
    
    if((a[0]=(int *)malloc(1024*(1+sizeof(double))*sizeof(int)))==NULL) {
        ret_code = -1;
        goto error01;
    }
    for(i=1;i<=sizeof(double);i++) {
        a[i] = a[i-1] + 1024;
    }
    for(i=0;i<size;i++) {
        b = (unsigned char *)(data + i);
        if(0x80 & b[sizeof(double)-1]) {
            for(j=0;j<sizeof(double);j++) {
                b[j] = ~b[j];
            }
        } else {
            b[sizeof(double)-1] ^= 0x80;
        }
    }
    
    american_flag_sort_c(data,size,a,sizeof(double));
    
    for(i=0;i<size;i++) {
        b = (unsigned char *)(data + i);
        if(0x80 & b[sizeof(double)-1]) {
            b[sizeof(double)-1] ^= 0x80;
        } else {
            for(j=0;j<sizeof(double);j++) {
                b[j] = ~b[j];
            }
        }
    }
    
    free(a[0]);
    error01:
    return ret_code;
}

####アメリカンフラッグソート(非再帰版)

int american_flag_sort(double *data,int size)
{
    int i,j,k,ret_code;
    int **a,*b;
    double **c;
    unsigned char *d;
    double tmp;
    ret_code = 0;
    
    i  = (1+sizeof(double))*sizeof(int *);
    i  = ((i + sizeof(double *) - 1)/sizeof(double *))*sizeof(double *);
    i += sizeof(double)*sizeof(double *);
    i  = ((i + sizeof(int) -1)/sizeof(int))*sizeof(int);
    i += 257*(1+sizeof(double))*sizeof(int);
    i += 2*sizeof(double)*sizeof(int);
    if((a=(int **)malloc(i))==NULL) {
        ret_code = -1;
        goto error01;
    }
    i  = (1+sizeof(double))*sizeof(int *);
    j  = (i + sizeof(double *) - 1)/sizeof(double *);
    i  = j * sizeof(double *);
    c  = ((double **)a) + j;
    i += sizeof(double)*sizeof(double *);
    j  = (i + sizeof(int) -1)/sizeof(int);
    a[0]  = ((int *)c) + j;
    for(i=1;i<=sizeof(double);i++) {
        a[i] = a[i-1] + 257;
    }
    b = a[sizeof(double)] + 257;
    
    for(i=0;i<size;i++) {
        d = (unsigned char *)(data + i);
        if(0x80 & d[sizeof(double)-1]) {
            for(j=0;j<sizeof(double);j++) {
                d[j] = ~d[j];
            }
        } else {
            d[sizeof(double)-1] ^= 0x80;
        }
    }
    b[sizeof(double)-1] = size;
    b[2*sizeof(double)-1] = 0;
    c[sizeof(double)-1] = data;
    i=sizeof(double)-1;
    while(1) {
        for(j=0;j<257;j++) {
            a[i][j] = 0;
        }
        for(j=0;j<b[i];j++) {
            d = (unsigned char *)(c[i] + j);
            a[i][1+d[i]]++;
        }
        for(j=0;j<256;j++) {
            a[i][j+1] += a[i][j];
            a[sizeof(double)][j] = a[i][j+1];
        }
        d = (unsigned char *)(&tmp);
        for(j=0;j<256;j++) {
            for(k=a[i][j];k<a[sizeof(double)][j];) {
                tmp = c[i][k];
                if(j != d[i]) {
                    c[i][k] = c[i][a[i][d[i]]];
                    c[i][a[i][d[i]]] = tmp;
                } else {
                    k++;
                }
                a[i][d[i]]++;
            }
        }
        a[i][0] = 0;
        for(j=0;j<256;j++) {
            a[i][j+1] = a[sizeof(double)][j];
        }
        k = 0;
        if(i != 0 && b[i]>1) {
            k = 0;
            while(a[i][1+k] - a[i][k] == 0 && k < 256) k++;
            if(k < 256) {
                c[i-1] = c[i] + a[i][k];
                b[i-1] = a[i][1+k] - a[i][k];
                b[sizeof(double)+i] = k+1;
                k=0;
                i--;
            } else {
                k=1;
            }
        } else {
            k = 1;
        }
        if(k) {
            j = i+1;
            while(j<sizeof(double)) {
                k = b[sizeof(double)+j];
                while(a[j][1+k] - a[j][k] == 0 && k < 256) {
                    k++;
                }
                if(k == 256) {
                    b[sizeof(double)+j] = 256;
                    j++;
                } else {
                    break;
                }
            }
            if(j==sizeof(double)) {
                goto end;
            }
            c[j-1] = c[j] + a[j][k];
            b[j-1] = a[j][1+k] - a[j][k];
            b[sizeof(double)+j] = k + 1;
            i=j-1;
        }
    }
    end:
    
    for(i=0;i<size;i++) {
        d = (unsigned char *)(data + i);
        if(0x80 & d[sizeof(double)-1]) {
            d[sizeof(double)-1] ^= 0x80;
        } else {
            for(j=0;j<sizeof(double);j++) {
                d[j] = ~d[j];
            }
        }
    }

    free(a);
    error01:
    return ret_code;
}

####クイックソート(再帰版)

void quick_sort(double *a,int size)
{
    int i,j;
    double p,q;
    if(size >= 3) {
        if(a[0] < a[size/2]) {
            if(a[size/2] < a[size-1]) {
                p = a[size/2];
            } else if (a[size-1] < a[0]){
                p = a[0];
            } else {
                p = a[size-1];
            }
        } else {
            if(a[size/2] > a[size-1]) {
                p = a[size/2];
            } else if (a[size-1] > a[0]){
                p = a[0];
            } else {
                p = a[size-1];
            }
        }
    } else if(size == 2) {
        p = a[0];
    } else {
        return;
    }
    i = 0;
    j = size -1;
    while(1) {
        while(a[i] < p) i++;
        while(a[j] > p) j--;
        if(i>=j) break;
        q = a[i];
        a[i] = a[j];
        a[j] = q;
        i++;
        j--;
    }
    quick_sort(a,i);
    j++;
    i = size - j;
    quick_sort(a+j,i);
    return;
}

####クイックソート(非再帰版)

int quick_sort(double *a,int size)
{
    int i,j,k;
    double p,q;
    int *stack;
    
    if((stack = (int *)malloc(16*sizeof(int)*sizeof(int))) == NULL) {
        return 0;
    }
    stack[0] = 0;
    stack[1] = size;
    i = 0;
    while(i>=0) {
        if(stack[i*2+1] - stack[i*2+0] >= 3) {
            k = (stack[i*2+1] + stack[i*2+0])/2;
            if(a[stack[i*2+0]] < a[k]) {
                if(a[k] < a[stack[i*2+1]-1]) {
                    p = a[k];
                } else if(a[stack[i*2+0]] < a[stack[i*2+1]-1]) {
                    p = a[stack[i*2+1]-1];
                } else {
                    p = a[stack[i*2+0]];
                }
            } else {
                if(a[k] > a[stack[i*2+1]-1]) {
                    p = a[k];
                } else if(a[stack[i*2+0]] < a[stack[i*2+1]-1]) {
                    p = a[stack[i*2+0]];
                } else {
                    p = a[stack[i*2+1]-1];
                }
            }
        } else if(stack[i*2+1] - stack[i*2+0] == 2) {
            p = a[stack[i*2+0]];
        } else {
            i--;
            continue;
        }
        j = stack[i*2+0];
        k = stack[i*2+1] -1;
        while(1) {
            while(a[j] < p) j++;
            while(a[k] > p) k--;
            if(j>=k) break;
            q = a[j];
            a[j] = a[k];
            a[k] = q;
            j++;
            k--;
        }
        if(j - stack[i*2+0] < stack[i*2+1] - k - 1) {
            stack[i*2+2] = stack[i*2+0];
            stack[i*2+3] = j;
            stack[i*2+0] = k+1;
        } else {
            stack[i*2+2] = k+1;
            stack[i*2+3] = stack[i*2+1];
            stack[i*2+1] = j;
        }
        i++;
    }
    free(stack);
    return 0;
}

##プログラミングの難易度
スムースソート > 非再帰アメリカンフラッグソート > その他
ヒープソートが簡単だったので舐めてかかったら意外と難しかった

##扱い易さ
非再帰マージソート > ヒープソート > その他

クイックソートは再帰だとスタック消費量が恐ろしいかといって非再帰だと面倒
簡単な挿入ソートは計算オーダが $ O(n^2) $ で遅すぎる

ある程度簡単でそれなりに速くなおかつ非再帰なソート $ = $ とっても扱いやすい

45
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?