首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言實作:單向循環鏈表建立與操作完整教學(含圖解邏輯)

     編輯:關於C語言

資料結構:單向循環鏈表

特點:最後一個節點的 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)
}

核心邏輯圖解

  1. 初始化:head->next = head 空表自環
  2. 插入第一節點:head->next = newNode; tail = newNode
  3. 後續插入:tail->next = newNode; tail = newNode
  4. 閉環:tail->next = head

常用操作函數

遍歷列印

void 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 歸零
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved