輸入若干學生(姓名、出生年月日),輸出生日相同的學生總數。要求用 C 語言模擬面向對象:封裝日期結構、重載比較運算、學生結構包含日期。
// 日期結構:封裝年月日,提供比較函數
typedef struct {
int year, month, day;
int key; // 年*10000 + 月*100 + 日,便於快速比較
} Date;
// 學生結構:包含姓名指針與日期結構
typedef struct {
char *name;
Date birthday;
} Student;
// 學生列表:動態數組
typedef struct {
Student *data;
int count, capacity;
} StudentList;
// 日期初始化並計算 key
Date make_date(int y, int m, int d) {
Date dt = {y, m, d, y*10000 + m*100 + d};
return dt;
}
// 學生創建
Student make_student(const char *name, int y, int m, int d) {
Student s;
s.name = strdup(name); // 需後續 free
s.birthday = make_date(y, m, d);
return s;
}
// 比較函數:供 qsort 使用
int cmp_student(const void *a, const void *b) {
return ((Student*)a)->birthday.key - ((Student*)b)->birthday.key;
}
// 統計相同生日總人數
int count_same_birthday(StudentList *list) {
if (list->count == 0) return 0;
qsort(list->data, list->count, sizeof(Student), cmp_student);
int total = 0;
int i = 0;
while (i < list->count) {
int j = i + 1;
while (j < list->count && list->data[j].birthday.key == list->data[i].birthday.key)
j++;
int group_size = j - i;
if (group_size > 1) total += group_size; // 只有同組>1人才計入
i = j;
}
return total;
}
int main() {
StudentList list = {0};
list.capacity = 10;
list.data = malloc(list.capacity * sizeof(Student));
// 示例數據(實際可從 stdin 讀取)
list.data[list.count++] = make_student("XiaoZhang", 1994, 5, 1);
list.data[list.count++] = make_student("XiaoWang", 1994, 5, 1);
list.data[list.count++] = make_student("XiaoLi", 1994, 6, 3);
list.data[list.count++] = make_student("XiaoChen", 1994, 6, 3);
list.data[list.count++] = make_student("XiaoDong", 1994, 8, 1);
int result = count_same_birthday(&list);
printf("生日相同的學生總數:%d\n", result); // 輸出 4
// 釋放內存
for (int i = 0; i < list.count; i++) free(list.data[i].name);
free(list.data);
return 0;
}
| 方案 | 時間複雜度 | 空間複雜度 | 備註 |
|---|---|---|---|
| 排序+線性掃描 | O(n log n) | O(1) 額外 | 通用、穩定 |
| 哈希表計數 | O(n) 平均 | O(n) | 需實現哈希表或用第三方庫 |
| 位圖/計數排序 | O(n + range) | O(range) | 生日範圍固定(365*年數)可行 |
init()/destroy() 約定俗成命名qsort/bsearch