データ構造とアルゴリズム第13回
知能情報学メジャー和⽥俊和
5整列5.1整列とは5.2単純な整列アルゴリズム5.3挿⼊ソートとその拡張5.4ヒープソート5.5クイックソート5.6マージソート5.7値の⽐較を⽤いない整列
5.6マージソート①与えられたデータ𝐴を
𝐴"と𝐴#にほぼ⼆等分する.
②𝐴"と𝐴#を整列する.このとき,データ数が1であれば,整列済み.これ以外の場合, 𝐴"と𝐴#に対してマージソートの⼿続きを適⽤する.
③整列された𝐴"と𝐴#をマージする.
5.6マージソート
マージ処理(⼩さい⽅を出⼒する)
Cプログラムの例
#include<stdio.h>
voidmerge(intA[],intleft,intmid,intright){
inti,j,k,B[right-left+1];i=left;j=mid+1;k=0;while(i<=mid&&j<=right){
if(A[i]<=A[j]){B[k++]=A[i++];
}else{B[k++]=A[j++];
}}if(i==mid+1){
while(j<=right){B[k++]=A[j++];
}}else{
while(i<=mid){B[k++]=A[i++];
}}for(i=0,j=left;j<=right;i++,j++)A[j]=B[i];
}
voidmerge_sort(intA[],intleft,intright){
intp,mid;mid=(left+right)/2;if(left<mid)merge_sort(A,left,mid);if(mid+1<right)merge_sort(A,mid+1,right);merge(A,left,mid,right);
}
voidPrintArray(intA[],intn){略}
intmain(){
intA[]={32,43,15,25,8,9,1,2,5,13};
PrintArray(A,10);merge_sort(A,0,9);PrintArray(A,10);
}
5.6 マージソート•マージソートにおける時間計算量•平均時間計算量も最悪時間計算量も𝑂 𝑛 log 𝑛•整列のために同じサイズの配列がもう⼀つ必要になる.•外部整列に向いている.(コラム参照)
[コラム]整列アルゴリズムの計算量の下界
•整列は要素間に成⽴する⼤⼩関係を決定すること•これは2分決定⽊で表現できる.•この決定⽊の⾼さは,𝑂(𝑛 log 𝑛)である.•これが整列アルゴリズムの下界となる.
x<y<z,x<z<y,y<x<z,y<z<x,z<x<y,z<y<x
x<y<z,x<z<y,z<x<y
y<x<z,y<z<x,z<y<x
x<y y<x
x<z
x<y<z,x<z<y,
z<x
z<x<y
y<z z<y
x<y<z x<z<y
x<z
y<x<z
z<x
y<z<x,z<y<x
y<z z<y
y<z<x z<y<x
5.7 値の⽐較を⽤いない整列• 5.7.1バケットソート• 5.7.2基数ソート
5.7.1バケットソート• 0〜𝑀 − 1の整数値を取るデータに対して,0〜𝑀 − 1の添え字のついた𝑀個のバケットを⽤意しておく• 整列対象のデータを1つずつ順に対応するバケットに⼊れていく• すべてのデータをバケットに⼊れ終えた時点で,バケットの内容を順番に読み出せば整列が終わる.
5.7.1バケットソート同じデータを格納できるようにキューを使う
Cプログラムの例
#include<stdio.h>#include<stdlib.h>#defineNum50charQueue[Num];intfront=0;intrear=0;#defineEMPTY-1
voidinit_queue(){
inti;for(i=0;i<Num;i++)Queue[i]=EMPTY;
}
intdequeue(){
if(front==rear)returnEMPTY;returnQueue[front++];
}
voidPrintArray(intA[],intn){略}
voidbucket_sort(intA[],intn){
inti,max,d;init_queue();max=A[0];for(i=0;i<n;i++){
Queue[A[i]]=A[i];if(A[i]>max)max=A[i];
}rear=max+1;i=0;while(front<rear){
d=dequeue();if(d!=EMPTY)A[i++]=d;
}}
intmain(){
intA[]={32,43,15,25,8,9,1,2,5,13};PrintArray(A,10);bucket_sort(A,10);PrintArray(A,10);
}
5.7.2基数ソート• 𝑘桁の𝑟進数の場合,各桁の値は0〜𝑟 − 1である.•各桁を下の桁から順にバケットソートで整列し,順に読み出し,⼀つ上の桁のバケットソートを⾏う.
Cプログラムの例
#include<stdio.h>#include<stdlib.h>#defineRadix10typedefstructcell{
intdata;structcell*next;
}Cell;Cell*Bucket[Radix];intindx;
voidInit(){
inti;for(i=0;i<Radix;i++)Bucket[i]=NULL;
}
Cell*AllocCell(intd){
Cell*rv;rv=(Cell*)malloc(sizeof(Cell));rv->data=d;rv->next=NULL;returnrv;
}
voidinsert_cell_top(Cell**H,intd){
Cell*New;New=AllocCell(d);New->next=*H;*H=New;
}
voidinsert(inta,intd){
insert_cell_top(&Bucket[a],d);}
voidrecursive_set(Cell*H,intA[]){
if(H->next!=NULL){recursive_set(H->next,A);
}A[indx++]=H->data;free(H);
}
Cプログラムの例(続き)
voidread_and_set(intA[]){
inti;for(i=0;i<Radix;i++){
if(Bucket[i]!=NULL){recursive_set(Bucket[i],A);Bucket[i]=NULL;
}}
}
voidradix_sort(intA[],intn){
inti,j,r=1,flag=1;Cell*H;while(flag){
flag=0;for(i=0;i<n;i++){
insert((A[i]/r)%Radix,A[i]);if((A[i]/r)%Radix!=0)flag=1;
}if(flag==0)break;indx=0;read_and_set(A);r=r*Radix;
}}
voidPrintArray(intA[],intn){略}
intmain(){
intA[]={32,43,15,25,8,9,1,2,5,13};
PrintArray(A,10);radix_sort(A,10);PrintArray(A,10);
}
プログラミング上の補⾜知識•⼀つのソートプログラムで,昇順にも,降順にも並べ替える⽅法は?•⼀つのソートプログラムで,整数も⽂字列も並べ替える⽅法は?
答え:関数のポインタを使う.次は単純挿⼊法を関数のポインタで書いた例
単純挿⼊法Cプログラムの例#include<stdio.h>
voidinsertion_sort(intA[],intn){
inti,j,d;for(i=1;i<n;i++){
d=A[i];j=i-1;while((j>=0)&&(d< A[j])){
A[j+1]=A[j];j--;
}A[j+1]=d;
}}
voidPrintArray(intA[],intn){
inti;for(i=0;i<n;i++)printf("%d,",A[i]);printf("¥n");
}
intmain(){
intA[]={32,43,15,25,8,9,1,2,5,13};
PrintArray(A,10);insertion_sort(A,10);PrintArray(A,10);
}
関数ポインタを⽤いた単純挿⼊法のプログラム
#include<stdio.h>intcomp1(inta,intb){return(a<b);}intcomp2(inta,intb){return(a>b);}
voidinsertion_sort(intA[],intn, int(*cmp)(int,int)){
inti,j,d;for(i=1;i<n;i++){
d=A[i];j=i-1;while((j>=0)&&(cmp(d,A[j]))){
A[j+1]=A[j];j--;
}A[j+1]=d;
}}
voidPrintArray(intA[],intn){
inti;for(i=0;i<n;i++)printf("%d,",A[i]);printf("¥n");
}
intmain(){
intA[]={32,43,15,25,8,9,1,2,5,13};
PrintArray(A,10);insertion_sort(A,10,comp1);PrintArray(A,10);insertion_sort(A,10,comp2);PrintArray(A,10);
}
twada$./a.out32,43,15,25,8,9,1,2,5,13,1,2,5,8,9,13,15,25,32,43,43,32,25,15,13,9,8,5,2,1,