首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 單鏈表創建與列印:指針傳遞錯誤深度解析

     編輯:程式設計綜合問答

初學 C/C++ 實現單鏈表時,最常見的錯誤是在 creat 函數中試圖修改主函數的頭結點指針,卻傳遞了指針的值而非地址,導致主函數的頭指針永遠不會被更新。本文透過您的代碼詳細剖析此問題並給出正確寫法。

錯誤代碼分析

void creat(LNode* L) {  // 參數是指針的「副本」
    List p = (List)malloc(sizeof(LNode));
    L = p;  // 修改的是副本,主函數的 L 不受影響
    // ...
}

void main() {
    LNode L;        // 棧上分配的結構體變量
    creat(&L);      // 傳遞 L 的地址 (LNode*)
    get(&L);
}

關鍵誤區:LNode L 是一個實體結構體,非指針。&L 的類型是 LNode* (即 List),傳入 creat(List L) 後,函數內部的 L 是這個地址的副本。當你在函數內做 L = p 時,只是讓局部副本指向新記憶體,主函數的 L 仍指向原棧記憶體,且其 next 從未被初始化,導致鏈表斷裂。

正確做法:雙重指針或引用

方案一:傳遞指針的指針 (C 風格)

void creat(List *L) {  // 參數類型改為 List* (即 LNode**)
    *L = (List)malloc(sizeof(LNode));  // 解引用修改主函數的指針值
    List p = *L;
    // ... 後續節點插入邏輯
}

void main() {
    List L = NULL;  // 定義為指針並初始化為 NULL
    creat(&L);      // 傳遞指針的地址
    get(L);         // 列印時直接傳指針值
}

方案二:使用 C++ 引用 (推薦)

void creat(List &L) {  // 引用參數,直接操作主函數的 L
    L = (List)malloc(sizeof(LNode));
    // ...
}

void main() {
    List L = NULL;
    creat(L);  // 呼叫時無需取址
    get(L);
}

列印函數 get 的邏輯修正

您原本的列印邏輯有兩個問題:

  1. p->next = p 造成自我循環,應為 p->next = NULL (尾插法需維護尾指針)。
  2. 列印時從 L 開始卻印 p->next->data,會漏掉第一個有效節點或讀取垃圾值。
void get(List L) {  // 傳值即可,不需修改頭指針
    List p = L;
    while (p != NULL) {
        printf("節點數據:%d\n", p->data);
        p = p->next;
    }
}

完整可運行範例 (C++ 風格)

#include <iostream>
#include <cstdlib>
using namespace std;

typedef struct LNode {
    int data;
    LNode* next;
} LNode, *List;

void creat(List &L) {
    L = (List)malloc(sizeof(LNode));
    L->next = NULL;
    List tail = L;
    int n, val;
    cout << "輸入1繼續添加,0結束: ";
    cin >> n;
    while (n) {
        cout << "輸入節點數據: ";
        cin >> val;
        List p = (List)malloc(sizeof(LNode));
        p->data = val;
        p->next = NULL;
        tail->next = p;
        tail = p;
        cout << "輸入1繼續添加,0結束: ";
        cin >> n;
    }
    // 移除哨兵頭節點 (若不需要)
    List head = L;
    L = L->next;
    free(head);
}

void get(List L) {
    for (List p = L; p != NULL; p = p->next)
        cout << "節點數據:" << p->data << endl;
}

int main() {
    List L = NULL;
    creat(L);
    get(L);
    return 0;
}

核心概念總結

場景參數類型函數內修改頭指針主函數調用
只需修改節點內容List L (指針值)L->data = ...creat(head)
需修改頭指針指向 (如建表、插入頭部)List &L (引用) 或 List *L (雙重指針)L = newNode 或 *L = newNodecreat(head) 或 creat(&head)

掌握「指針傳值 vs 引用/雙重指針」的區別,是玩轉 C/C++ 鏈表、樹等動態資料結構的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved