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

C 語言帶頭結點單鏈表插入排序:指針傳遞錯誤導致創建失效的根因與修正版

     編輯:程式設計疑難解答

原始代碼核心缺陷

int create(list *head) {  // 形參是指針副本
    head = t;             // 修改副本,無法影響主調 main 中的 head
    // ...
}
int main() {
    list *head = NULL;
    create(head);         // 傳遞 NULL 值,函數內修改無效
    insert(head);         // head 仍為 NULL,解引用崩潰
}

根因:C 語言只有「值傳遞」

  • 傳遞 list *head 實際是傳遞指針的副本(地址值)。
  • 函數內 head = t 只是修改副本指向新節點,主調的 head 仍為 NULL。
  • 後續 insert(head) 使用未初始化的 NULL 指針,訪問 head->next 觸發段錯誤。

修正方案:二級指針 或 返回值

方案一:返回新建頭結點(推薦,簡潔)

list* create() {
    list *head = (list*)malloc(sizeof(list));
    head->next = NULL;
    // 讀取首個數據...
    return head;  // 直接返回頭結點地址
}

int main() {
    list *head = create();  // 接收返回值
    insert(head);
    // ...
}

方案二:傳遞二級指針 list **head

void create(list **head) {
    *head = (list*)malloc(sizeof(list));
    (*head)->next = NULL;
    // ...
}

int main() {
    list *head = NULL;
    create(&head);  // 傳遞頭指針的地址
    insert(head);
}

完整修正版代碼(含插入排序邏輯優化)

#include 
#include 

typedef int ElemType;
typedef struct Node {
    ElemType data;
    struct Node *next;
} Node, *List;

List create() {
    List head = (List)malloc(sizeof(Node));
    head->next = NULL;
    int x;
    printf("Enter numbers (end with 0): ");
    while (scanf("%d", &x) == 1 && x != 0) {
        List node = (List)malloc(sizeof(Node));
        node->data = x;
        node->next = NULL;
        // 尾插法構建初始鏈表
        List p = head;
        while (p->next) p = p->next;
        p->next = node;
    }
    return head;
}

void insert_sorted(List head) {
    int x;
    while (scanf("%d", &x) == 1 && x != 0) {
        List node = (List)malloc(sizeof(Node));
        node->data = x;
        node->next = NULL;
        
        List prev = head, curr = head->next;
        while (curr && curr->data < x) {
            prev = curr;
            curr = curr->next;
        }
        node->next = curr;
        prev->next = node;
    }
}

void print_list(List head) {
    for (List p = head->next; p; p = p->next)
        printf("%d ", p->data);
    puts("");
}

int main() {
    List head = create();
    insert_sorted(head);
    print_list(head);
    // 釋放內存略
    return 0;
}

關鍵修正點總結

問題原代碼修正
頭指針未回傳void create(list *head)List create() 返回頭指針
插入排序邊界while(1) 無 m->next 判斷先行while(curr && curr->data < x) 安全推進
輸入結束標誌字符 '$' 與 %d 衝突改用整數 0 或 EOF 判斷
內存洩漏無 free主程序退出前遍歷釋放(略)

「指針傳遞要改變指針本身,必須傳指針的指針,或直接返回新指針」 —— 這是 C 語言鏈表操作的鐵律,牢記於心。

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