整列
整列アルゴリズムの実装
以下は,選択ソート,挿入ソート,ヒープソート,クイックソートの整列アルゴリズムを含むC言語プログラムであり,教科書リスト5.2, 5.5, 5.7 ~ 5.10 (pp.95 ~ 111) をベースに実装されている. ソースコードは,sort_collection.h,sort_collection.c,main_sort_collection.c に分割されている.
サンプルコードはこちらからダウンロード可能.
ヘッダーファイル sort_collection.h
#ifndef INCLUDE_GUARD_SORT_COLLECTION_H
#define INCLUDE_GUARD_SORT_COLLECTION_H
extern unsigned long compare_count;
void cmp_cnt_reset(void);
void display(int a[], int n);
void selection_sort(int a[], int n);
void insertion_sort(int a[], int n);
void heap_sort(int a[], int n);
void q_sort(int a[], int n);
#endif // INCLUDE_GUARD_SORT_COLLECTION_H
ソースファイル sort_collection.c
#include <stdio.h>
#include <stdlib.h>
#include "sort_collection.h"
unsigned long compare_count = 0;
void cmp_cnt_reset(void) {
compare_count = 0;
}
int compare(int ldata, int rdata) {
compare_count++;
if (ldata < rdata) return -1;
else if (ldata == rdata) return 0;
else return 1;
}
void swap(int a[], int lidx, int ridx) {
int temp = a[lidx];
a[lidx] = a[ridx];
a[ridx] = temp;
}
void display(int a[], int n) {
int i;
for (i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
}
void selection_sort(int a[], int n) {
int i, j;
for (i = 0; i < n - 1; i++) {
int min = i;
for (j = i + 1; j < n; j++) {
if (compare(a[j], a[min]) == -1) {
min = j;
}
}
swap(a, i, min);
}
}
// Insertion sort
/**************************************/
void insertion_sort(int a[], int n) { ... }
// Functions for Heap sort
/**************************************/
void sift_down(int a[], int i, int n) { ... }
void build_heap (int a[], int n) { ... }
void heap_sort (int a[], int n) { ... }
// Functions for Quick sort
/**************************************/
int partition(int a[], int pivot, int left, int right) { ... }
void quick_sort(int a[], int left, int right) { ... }
void q_sort(int a[], int n) {
quick_sort(a, 0, n-1);
}
ソースファイル main_sort_collection.c
#include <stdio.h>
#include <stdlib.h>
#include "sort_collection.h"
int GetRandom(int min, int max) {
return min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
}
int main(int argc, char *argv[]) {
if (argc != 1) {
int numdata = atoi(argv[1]); // set numdata with cmd. argument
int *array = (int*)malloc(sizeof(int) * numdata);
int i;
printf("Enter %d integers\n", numdata);
for (i = 0; i < numdata; i++) {
scanf("%d", &array[i]); // enter integers
}
selection_sort(array, numdata);
printf("sorting result\n");
display(array, numdata);
printf("# of comparisons: %lu\n", compare_count);
free(array);
} else {
int numdata;
for (numdata = 1000; numdata <= 10000; numdata += 1000) { // numdata is 1000, 2000, ..., 10,000
int *array = (int*)malloc(sizeof(int) * numdata);
int i;
for (i = 0; i < numdata; i++) {
array[i] = GetRandom(0, (numdata * 10 - 1)); // random number from 0 to numdata * 10 - 1
}
selection_sort(array, numdata);
printf("%d %lu\n", numdata, compare_count);
cmp_cnt_reset();
free(array);
}
}
return EXIT_SUCCESS;
}
コンパイルと実行
以下の内容の Makefile を作成する.
ファイル Makefile
sort_collection: sort_collection.o main_sort_collection.o
コマンドラインでmakeコマンドを実行すると,Cコンパイラによって実行ファイルが生成される.
mac$ make
cc -c -o sort_collection.o sort_collection.c
cc -c -o main_sort_collection.o main_sort_collection.c
cc sort_collection.o main_sort_collection.o -o sort_collection
numdata をコマンドライン引数として与えると,numdata 個の整数の入力が要求され,整列結果及び比較回数が表示される.
mac$ ./sort_collection 5
Enter 5 integers
3
1
5
4
2
sorting result
1 2 3 4 5
# of comparisons: 10
mac$
コマンドライン引数を与えないと,main 関数の else 部分が実行される.
mac$ ./sort_collection
1000 499500
2000 1999000
3000 4498500
4000 7998000
5000 12497500
6000 17997000
7000 24496500
8000 31996000
9000 40495500
10000 49995000
mac$
基本課題
- 挿入ソート,ヒープソート,クイックソートを実装し,以下の要件を確認すること.なお,関数 swap, compare を改変し,動作の様子を確認できるようにした場合は加点する.
- 関数 sift_down, build_heap, partition が正しく動作すること.
- 各ソートについて, 6 ~ 8 個程度のデータを実際に整列する例を示し,動作について説明すること.
- ヒープソートおよびクイックソートの性能を分析せよ.
- ランダムな入力データを要素として持つ大きさ numdata (numdata = 1000, 2000, ..., 10,000)の配列を生成し,各整列法を実行し,整列に要するデータの比較回数を調べ,結果をグラフを用いて分析すること.
- ランダムな入力データを要素として持つ配列を生成し,各整列法を実行し,整列に要する実行時間を調べ,結果をグラフを用いて分析すること. 配列の大きさは,実行時間が0.1 ~ 数秒程度になるように選ぶこと (実行時間を調べる際には,課題3: ハッシュ法に記載した事項を念頭に置きましょう).
- クイックソートの計算量が最悪 (すなわち,O(n2)の計算量) になるような配列を生成し,最悪の場合の性能を整列に要するデータの比較回数を調べ,結果をグラフを用いて分析すること.
- 1 ~ 3 の実験結果から,クイックソートとヒープソートの性能について,比較,考察せよ.
発展課題
sort_collection に,基数ソート void radix_sort(int a[], int n, int k) を追加せよ.実装には,教科書 115 ~ 121 ページを参考にすること.
この基数ソートは,10進数の各桁にバケットソートを適用し,整数を整列するアルゴリズムであり,配列 a の各要素 a[i] は, 0 ≤ a[i] < 10k とする.
- 以下の要件を全て満たすことを確認すること.
- 整数143, 322, 246, 755, 123, 563, 514, 522を要素とする配列に対して動作を確認すること.
- 各桁の処理の後のバケットの内容を表示し,確認すること.
提出締切
2022年12月12日(月)13:30