原代碼四大核心錯誤
| 錯誤類別 | 代碼位置 | 問題描述 | 修正方案 |
| 參數傳遞 | creatKlist(Keylist L) | 結構體值傳遞,修改不生效 | 改為指針 creatKlist(Keylist* L) |
| 排序算法 | sort() | 單趟冒泡,非完整排序 | 雙重循環或用 qsort |
| 順序查找 | Seqsearch() | 下標越界、未處理未找到 | 從 len-1 遞減至 0,未找到返回 -1 |
| 折半查找 | Binsearch() | 下標基準錯(1-based)、計數邏輯錯、局部數組返回 | 0-based、動態分配結果、正確計數 |
修正後完整代碼(關鍵片段)
// 1. 參數傳指針
void creatKlist(Keylist* L) {
scanf("%d", &L->len);
for (int i = 0; i < L->len; i++) scanf("%d", &L->key[i]);
}
// 2. 正確冒泡排序
void sort(Keylist* L) {
for (int i = 0; i < L->len - 1; i++)
for (int j = 0; j < L->len - 1 - i; j++)
if (L->key[j] > L->key[j+1]) {
int t = L->key[j]; L->key[j] = L->key[j+1]; L->key[j+1] = t;
}
}
// 3. 順序查找:返回下標或 -1
int Seqsearch(Keylist* L, int k) {
for (int i = L->len - 1; i >= 0; i--)
if (L->key[i] == k) return i;
return -1;
}
// 4. 折半查找:返回 {index, count},動態分配
int* Binsearch(Keylist* L, int k) {
int* res = malloc(2 * sizeof(int));
res[0] = -1; res[1] = 0;
int low = 0, high = L->len - 1;
while (low <= high) {
int mid = (low + high) / 2;
res[1]++;
if (L->key[mid] == k) { res[0] = mid; return res; }
else if (L->key[mid] < k) low = mid + 1;
else high = mid - 1;
}
return res;
}
主函數調用修正
int main() {
Keylist L;
creatKlist(&L);
sort(&L);
int choice, k;
scanf("%d", &choice);
scanf("%d", &k);
switch (choice) {
case 1: {
int pos = Seqsearch(&L, k);
if (pos != -1) printf("位置:%d\n", pos + 1);
else printf("不存在\n");
break;
}
case 2: {
int* res = Binsearch(&L, k);
if (res[0] != -1) printf("位置:%d, 比較次數:%d\n", res[0]+1, res[1]);
else printf("不存在, 比較次數:%d\n", res[1]);
free(res);
break;
}
}
return 0;
}
核心知識點總結
- 結構體做參數必傳指針:否則函數內修改的是副本
- 數組下標 0-based:C 語言慣例,避免 +1/-1 錯誤
- 查找失敗返回 -1:而非 0,因為 0 是合法下標
- 動態分配返回數組:局部數組函數返回後失效,必須 malloc/new 並文檔說明由調用者 free
- 折半查找前提:有序:必須先排序