// 典型頭插法創建單向循環鏈表
Node* p = new Node(x); // 新節點
p->next = p; // ① 自指向,形成單節點環
rear = p; // ② rear 指向該節點
p ──► [data=x | next=???] rear = NULL
節點剛分配,`next` 未初始化(野指針),`rear` 仍為空。
┌──────────────┐
│ ▼
p ──► [data=x | next]───┘ rear = NULL
▲ │
└──────────────┘
節點 `next` 指向自己,**構成只含一個節點的循環鏈表**。此時鏈表已「閉合」,但外部還沒有句柄持有它。
rear ──► [data=x | next]───┐
▲ │
└────────────────────┘
`rear` 指向該節點。**單向循環鏈表慣例:僅維護尾指針 `rear`**,頭節點可通過 `rear->next` O(1) 訪問,尾節點即 `rear` 本身。
p->next = rear->next; // 新節點 next 指向原頭節點
rear->next = p; // rear next 指向新節點
if (rear == NULL) rear = p; // 空表特判:rear 指向自己
// 或無需特判:若約定 rear 初始指向一個哨兵節點
**指向節點**。`rear` 是 `Node*`,指向鏈表最後一個節點。因為該節點 `next` 指向頭節點,整個環自然可達。**不要理解為指向「環」這個抽象概念**——C 指針只能指向具體內存地址。
Node* q = new Node(y);
q->next = rear->next; // q->next 指向原頭節點 x
rear->next = q; // x 變為第二個節點,rear->next 指向新頭 y
// rear 不變,仍指向尾節點 x
// 結構: rear→x→y→x... (循環)
圖示:
rear ──► [x | next]──┐
▲ │
│ ┌────┘
│ ▼
└───── [y | next]──┘
(新頭節點)
掌握這張圖,單向循環鏈表的增刪改查、Josephus 問題、循環隊列底層實現,全部迎刃而解。