/* merge-sort-number-2.c */ #include #define ARRAY_MAX 65535 int counter = 0; /* ソート対象配列へのデータの読み込み関数 */ int input_data(int array[]) { int i, d; for( i = 0; i < ARRAY_MAX; i++ ) { if ( scanf("%d", &d) == EOF ) { return i; } else { array[i] = d; } } fprintf(stderr, "Out of maximum amount(%d)", ARRAY_MAX); return i; } /* マージソート関数 array[]: ソート対象配列, left: 左端, right: 右端 */ void merge_sort(int array[], int left, int right) { int reserve[ARRAY_MAX / 2 + 1]; /* 前半部退避用の配列 */ int mid; /* 左端と右端の中間位置を示す変数 */ int i; /* 退避用配列の添え字のカウンタ */ int reserve_end; /* 退避用配列の右端 */ int j; /* ソート対象配列の後半部の添え字のカウンタ */ int k; /* ソート対象配列の添え字のカウンタ */ if ( left == right ) return; /* 配列の要素が空であれば何もせず戻る */ mid = (left + right) / 2; /* 配列の中間位置を求める */ merge_sort(array, left, mid); /* 再帰呼び出しにより前半部をソート */ merge_sort(array, mid + 1, right); /* 再帰呼び出しにより後半部をソート */ for( i = 0, k = left; k <= mid; i++, k++ ) { /* 前半部を退避 */ reserve[i] = array[k]; } i = 0; /* 退避された前半部の比較位置の初期値を設定 */ j = mid + 1; /* 後半部の比較位置の初期値を設定 */ reserve_end = mid - left; /* 退避された前半部の右端を設定 */ k = left; /* マージした結果の格納位置の初期値を設定 */ /* 退避された前半部、および後半部が残っている間、マージ */ while( i <= reserve_end && j <= right ) { counter++; /* 比較回数のカウント */ if ( reserve[i] >= array[j] ) { array[k] = reserve[i]; /* 退避された前半部からマージ */ i++; } else { array[k] = array[j]; /* 後半部からマージ */ j++; } k++; /* マージ位置を右に移動 */ } /* 比較によるマージ後、退避された前半部が残っていれば無条件にマージ */ while( i <= reserve_end ) { array[k] = reserve[i]; i++; k++; } } int main(int argc, char **argv) { int array[ARRAY_MAX]; /* ソート対象配列の用意 */ int amount; /* ソート対象配列の要素数 */ int i; amount = input_data(array); /* データ読み込み関数呼び出し */ merge_sort(array, 0, amount - 1); /* マージソート関数呼び出し */ for( i = 0; i < amount; i++ ) { /* 結果出力 */ printf("%d ", array[i] ); } printf("\n"); fprintf(stderr, "Number of comparisons is %d.\n", counter); }