C言語における配列のメモリレイアウトの理解から、ソートアルゴリズム、進数変換、行列演算といった実用的なアルゴリズムの実装まで、いくつかの例を通して解説します。
1. 配列のメモリレイアウトとアドレス
配列はメモリ上で連続した領域を占有します。以下の例では、1次元配列および2次元配列のアドレスと要素の配置を確認できます。
#include <stdio.h>
void inspect_array_memory() {
int arr[4] = {10, 20, 30, 40};
printf("配列全体のサイズ: %zu バイト\n", sizeof(arr));
for (int i = 0; i < 4; ++i) {
printf("要素 [%d] のアドレス: %p, 値: %d\n", i, &arr[i], arr[i]);
}
}
2. 中央値の算出とバブルソート
データセットから中央値(メディアン)を求めるには、まずデータを昇順に並べ替える必要があります。ここでは基本的なバブルソートアルゴリズムを使用します。
void sort_data(int data[], int size) {
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - i - 1; j++) {
if (data[j] > data[j + 1]) {
int temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
}
double calculate_median(int data[], int size) {
sort_data(data, size);
if (size % 2 == 0) {
return (data[size / 2 - 1] + data[size / 2]) / 2.0;
}
return (double)data[size / 2];
}
3. 進数変換の実装
10進数を任意の基数(2、8、16など)に変換するには、剰余演算を用いて各桁の値を抽出します。16進数への対応など、10を超える数値の表示にはアルファベットの活用が必要です。
void convert_base(int num, int base) {
char buffer[64];
int idx = 0;
while (num > 0) {
int remainder = num % base;
buffer[idx++] = (remainder > 9) ? (remainder - 10 + 'A') : (remainder + '0');
num /= base;
}
for (int i = idx - 1; i >= 0; i--) {
putchar(buffer[i]);
}
putchar('\n');
}
4. 行列の魔法陣判定
魔法陣(すべての行、列、および対角線の和が等しい正方行列)の判定は、各方向の合計を計算して比較することで行います。
int is_magic_square(int matrix[][100], int n) {
int target_sum = 0;
// 最初の行の和を基準とする
for (int j = 0; j < n; j++) target_sum += matrix[0][j];
// 行と列のチェック
for (int i = 0; i < n; i++) {
int row_sum = 0, col_sum = 0;
for (int j = 0; j < n; j++) {
row_sum += matrix[i][j];
col_sum += matrix[j][i];
}
if (row_sum != target_sum || col_sum != target_sum) return 0;
}
return 1;
}