特點:最後一個節點的 next 指向頭節點,形成閉環。優點:任一節點可遍歷全表、適合循環排程、Josephus 問題等。
typedef struct Node {
int data;
struct Node *next;
} Node;
Node* createCircularList(int n) {
if (n <= 0) return NULL;
Node *head = (Node*)malloc(sizeof(Node));
if (!head) { perror("head malloc failed"); exit(EXIT_FAILURE); }
head->next = head; // 空表自環
Node *tail = head;
for (int i = 1; i <= n; i++) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) { perror("node malloc failed"); exit(EXIT_FAILURE); }
newNode->data = i;
if (head->next == head) { // 第一個節點
head->next = newNode;
tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
}
tail->next = head; // 閉環
return tail; // 回傳尾節點(可經由 tail->next 取得 head)
}
head->next = head 空表自環head->next = newNode; tail = newNodetail->next = newNode; tail = newNodetail->next = headvoid printList(Node *tail) {
if (!tail) return;
Node *cur = tail->next; // head
do {
printf("%d ", cur->data);
cur = cur->next;
} while (cur != tail->next);
printf("\n");
}
bool insertAt(Node *tail, int pos, int val) {
if (!tail || pos < 1) return false;
Node *cur = tail->next;
for (int i = 1; i < pos && cur != tail; i++) cur = cur->next;
if (pos > 1 && cur == tail) return false; // 越界
Node *newNode = malloc(sizeof(Node));
newNode->data = val;
newNode->next = cur->next;
cur->next = newNode;
if (cur == tail) tail = newNode; // 插在尾部需更新尾指標
return true;
}
bool deleteNode(Node **tailPtr, int val) {
Node *tail = *tailPtr;
if (!tail) return false;
Node *prev = tail, *cur = tail->next;
do {
if (cur->data == val) {
prev->next = cur->next;
if (cur == tail) *tailPtr = prev; // 刪除尾節點
if (cur == cur->next) *tailPtr = NULL; // 唯一節點
free(cur);
return true;
}
prev = cur;
cur = cur->next;
} while (cur != tail->next);
return false;
}
void freeList(Node **tailPtr) {
Node *tail = *tailPtr;
if (!tail) return;
Node *cur = tail->next;
while (cur != tail) {
Node *tmp = cur;
cur = cur->next;
free(tmp);
}
free(tail);
*tailPtr = NULL;
}
int main() {
Node *tail = createCircularList(10);
printf("初始列表:"); printList(tail);
insertAt(tail, 5, 99);
printf("第5位插入99:"); printList(tail);
deleteNode(&tail, 99);
printf("刪除99:"); printList(tail);
freeList(&tail);
return 0;
}
| 錯誤 | 徵兆 | 修正 |
|---|---|---|
| 忘記閉環 | 遍歷無限迴圈或段錯誤 | 檢查 tail->next == head |
| 刪除尾節點未更新 tail | 尾指標成懸空指標 | 刪除時同步更新 *tailPtr |
| 單節點刪除邏輯缺漏 | free 後 head 仍指向已釋放記憶體 | 判斷 cur == cur->next 歸零 |