11.14

为啥不懂就问發表於2024-11-14

設計文件:連結串列逆置模組

  1. 問題描述
    本題要求實現一個函式,將給定的單向連結串列逆置,即表頭置為表尾,表尾置為表頭。給定連結串列的節點結構如下:

c
struct ListNode {
int data;
struct ListNode *next;
};
函式介面如下:

c
struct ListNode *reverse(struct ListNode *head);
其中,head 是使用者傳入的連結串列的頭指標。該函式需要將連結串列逆置,並返回逆置後的連結串列頭指標。

  1. 函式功能
    函式的核心功能是將單向連結串列逆置。具體而言:

輸入:單向連結串列的頭節點 head。
輸出:逆置後的單向連結串列的頭節點。
3. 演算法設計
連結串列逆置的基本思路是透過修改節點的 next 指標來反轉連結串列的方向。

初始化一個 prev 指標,表示已經處理的部分,初始化為 NULL。
遍歷連結串列,每次更新當前節點的 next 指標,使其指向前一個節點。
依次處理連結串列中的每個節點,直到遍歷完連結串列。
具體步驟:

初始化 prev 為 NULL,curr 為連結串列的頭節點。
遍歷連結串列,對於每個節點:
儲存當前節點的下一個節點 next。
將當前節點的 next 指標指向 prev,即反轉指向關係。
移動 prev 和 curr 指標向前。
最終,prev 會指向連結串列的最後一個節點,即新的頭節點。
4. 模組圖
由於目前不支援插入圖片,因此請參考以下文字描述手繪模組圖:

+------------------------+
| 輸入:連結串列頭節點 head |
+------------------------+
|
V
+------------------------+
| 初始化指標 prev=NULL |
+------------------------+
|
V
+------------------------+
| 遍歷連結串列,更新指標 next |
+------------------------+
|
V
+------------------------+
| 返回反轉後的頭節點 |
+------------------------+
5. 程式碼實現
c

include <stdio.h>

include <stdlib.h>

struct ListNode {
int data;
struct ListNode *next;
};

// 反轉連結串列函式
struct ListNode *reverse(struct ListNode *head) {
struct ListNode *prev = NULL, *curr = head, *next = NULL;

// 遍歷連結串列
while (curr != NULL) {
    next = curr->next;  // 儲存當前節點的下一個節點
    curr->next = prev;  // 反轉當前節點的next指標
    prev = curr;        // prev向後移動
    curr = next;        // curr向後移動
}

return prev;  // 返回新的頭節點

}

// 輔助函式:建立連結串列
struct ListNode *createlist() {
int value;
struct ListNode *head = NULL, *tail = NULL;

// 輸入連結串列資料
while (scanf("%d", &value) && value != -1) {
    struct ListNode *new_node = (struct ListNode *)malloc(sizeof(struct ListNode));
    new_node->data = value;
    new_node->next = NULL;
    
    if (head == NULL) {
        head = new_node;
        tail = new_node;
    } else {
        tail->next = new_node;
        tail = new_node;
    }
}

return head;

}

// 列印連結串列
void printlist(struct ListNode *head) {
struct ListNode *p = head;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}

int main() {
struct ListNode *head;

// 建立連結串列並逆置
head = createlist();
head = reverse(head);

// 列印逆置後的連結串列
printlist(head);

return 0;

}
6. 程式碼解釋
reverse 函式:

prev 指標用來記錄已反轉部分的尾節點。
curr 指標用來遍歷連結串列中的節點。
next 用來儲存當前節點的下一個節點,以避免斷鏈。
反轉過程中,每次將當前節點的 next 指標指向 prev,然後更新 prev 和 curr。
最終返回的 prev 是反轉後的連結串列頭。
createlist 函式:

動態建立連結串列,直到輸入 -1 時停止。
每個新節點透過 malloc 建立,並將其連結到連結串列的尾部。
printlist 函式:

遍歷連結串列並列印每個節點的資料。
7. 測試樣例
輸入樣例:

1 2 3 4 5 6 -1
輸出樣例:

6 5 4 3 2 1
8. 時間與空間複雜度
時間複雜度:

由於我們只需要遍歷連結串列一次,時間複雜度為 O(n),其中 n 是連結串列中的節點數。

空間複雜度:

我們只使用了常數空間儲存指標,因此空間複雜度為 O(1)。

  1. 總結
    該函式實現了連結串列的反轉,並透過指標操作實現了高效的反轉演算法。函式遵循連結串列的基本操作原則,時間和空間複雜度均為最優解。