日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

不带头节点的单链表如何头插(多图易懂)

發布時間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不带头节点的单链表如何头插(多图易懂) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 緣起
    • 帶頭節點的頭插
    • 不帶頭節點的頭插
      • 錯誤的代碼
      • 為什么錯誤
      • 如何修改
        • 返回新的頭指針
        • 二級指針

緣起

本文想說的是單向非循環鏈表的頭插。單向非循環鏈表,可以是帶頭節點的,也可以是不帶頭節點的。

對于前者,代碼比較簡單,后文會說。對于后者,不帶頭節點的單向鏈表的頭插,我發現即使有多年工作經驗的老鳥,也可能寫出錯誤的代碼。

帶頭節點的頭插

#include <stdio.h> #include <assert.h> #include <stdlib.h>typedef struct node{int data;struct node *next; }node_t;node_t *create_list(void) {node_t *head = malloc(sizeof(node_t));if(head == NULL){printf("create list failed\n");return NULL;}head->next = NULL;return head; }int insert_head(node_t *head, int num) {assert(head != NULL);node_t *node = malloc(sizeof(node_t));if(node == NULL)return -1;node->data = num;node->next = head->next;head->next = node;return 0; }void printf_list(node_t *head) {assert(head != NULL);if(head->next == NULL){printf("the list is empty\n");return;}node_t *temp = head->next;while(temp){printf("%d\n",temp->data);temp = temp->next;} }int main(void) {int a[]={1,2,3,4,5,6};node_t *head = create_list();if(head == NULL)return -1;for(int i = 0; i < sizeof(a)/sizeof(a[0]); ++i){insert_head(head, a[i]);}printf_list(head);return 0; }

運行結果是:

6 5 4 3 2 1

不帶頭節點的頭插

錯誤的代碼

把上面的代碼改動一下,就可以得到一份錯誤的代碼!

#include <stdio.h> #include <assert.h> #include <stdlib.h>typedef struct node{int data;struct node *next; }node_t;node_t *head = NULL; // 全局變量,鏈表的頭指針int insert_head(node_t *head, int num) {node_t *node = malloc(sizeof(node_t));if(node == NULL)return -1;node->data = num;node->next = head;head = node; // !!!!!! 這里是有問題的return 0; }void printf_list(node_t *head) { if(head == NULL){printf("the list is empty\n");return;}node_t *temp = head;while(temp){printf("%d\n",temp->data);temp = temp->next;} }int main(void) {int a[]={1,2,3,4,5,6};for(int i = 0; i < sizeof(a)/sizeof(a[0]); ++i){insert_head(head, a[i]);}printf_list(head);return 0; }

你猜運行結果是什么?

結果是:

the list is empty

為什么錯誤

插入操作失敗了。罪魁禍首就是這個函數

int insert_head(node_t *head, int num) {node_t *node = malloc(sizeof(node_t));if(node == NULL)return -1;node->data = num;node->next = head;head = node; // !!!!!! 這里是有問題的return 0; }

為什么不對呢?畫圖說明。

假設有一個單向鏈表,頭指針 head 的值是 0x200,也就是第一個節點的地址。

調用 insert_head 函數,假設調用者傳遞的參數是頭指針 head 和數字 3(實參),用藍色表示。

在調用函數時,系統會把實參的值傳遞給被調用函數的形參(單向拷貝);

int insert_head(node_t *head, int num) 中的 head 和 num 就是形參;

這里的 head 和全局變量 head 同名,但不是一回事:全局變量 head 是實參,這里的 head 是形參,當然也可以取別的名字;

形參屬于函數內的局部變量,在函數被調用的時候,形參的內存在棧上分配,函數執行完畢后,分配的內存被釋放,即棧幀被銷毀。

假設已經完成了值的拷貝,咱們繼續分析:

代碼中有三行我標成紅色。

首先分配節點的內存,在堆上分配(假設地址是 0x300),用深藍色表示;然后用 num 和 head 給節點的成員賦值,這都沒有問題。繼續執行。

注意這句話: head = node;

這導致棧上的 head = 0x300;似乎達到了目的,讓 head 指向新插入的節點,但是,函數返回后,棧上的變量都會消失。

最后剩下什么?

鏈表還是原來的鏈表,頭指針 head 依然指向 0x200;

唯一剩下的就是分配了一個新節點,且這個新節點指向舊的第一個節點。

如何修改

如果要修改錯誤的代碼,我提供兩個思路,第一個就是根據上面的圖,返回新的頭指針,第二個是用二級指針。

返回新的頭指針

node_t *insert_head_2(node_t *head, int num) {node_t *node = malloc(sizeof(node_t));if(node == NULL){printf("malloc failed\n");return head;}node->data = num;node->next = head;return node; // 返回新的頭指針 }

主函數修改為:

int main(void) {int a[]={1,2,3,4,5,6};for(int i = 0; i < sizeof(a)/sizeof(a[0]); ++i){head = insert_head_2(head, a[i]); }printf_list(head);return 0; }

也就是說每次插入都要刷新頭指針。

二級指針

再看第二個方法。

咱們深挖一下這張圖,我們的目的不是修改 head 的值,因為他只是頭指針的一份拷貝,無論怎么修改,都無法修改函數外面的那個頭指針。

那怎么辦?我們可以傳進來頭指針的地址,跑得了和尚跑不了廟,既然拿到了你的內存地址,還怕修改不了你的值?這就是 C 語言的威力,給我一根指針,我能戳動地球!

代碼可以這樣寫:

int insert_head_3(node_t **head, int num) {node_t *node = malloc(sizeof(node_t));if(node == NULL){printf("malloc failed\n");return -1;}node->data = num;node->next = *head;*head = node; // 修改頭指針的值return 0;}

主函數修改為

int main(void) {int a[]={1,2,3,4,5,6};for(int i = 0; i < sizeof(a)/sizeof(a[0]); ++i){insert_head_3(&head, a[i]);}printf_list(head);return 0; }

再用圖解釋一下:

假設頭指針 head 的地址是 0x800

傳參完成后(下圖中的黃色部分),分配新節點的內存,在堆上分配(假設地址是 0x300),用深藍色表示;然后用 num 和 *head 給節點的成員賦值;

注意,*head 表示地址 0x800 中的內容,即 0x200

還有,棧上的變量 head 指向了全局變量——頭指針 head

最后一步:修改頭指針的值,*head = node;

也就是說,不是把新節點的地址 0x300 賦值給棧上的變量 head,而是賦值給 head 指向的內存。

可以看到,修改成功,頭指針確實指向了新節點。

【end】

總結

以上是生活随笔為你收集整理的不带头节点的单链表如何头插(多图易懂)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产成人精品网 | 久久久精品一区二区三区 | 都市激情亚洲一区 | 69日本xxxxxxxx96 | 午夜777 | 能看毛片的网站 | 欧美日一区二区三区 | 久久久精品蜜桃 | 亚洲av无码国产精品久久不卡 | 伊在线久久丫 | 91精品国产入口 | 一区中文字幕 | 亚洲高清无码久久 | 成人性生交大片免费卡看 | 亚洲国产精品va在线看黑人 | 在线欧美国产 | 欧美无极品 | 性欧美熟妇videofreesex | 亚洲一区二区三区四区五区午夜 | 999福利视频 | 日本精品视频在线 | 韩国av免费在线观看 | 欧美成人精精品一区二区频 | 久久伊人精品 | 国产精品久久久久久人妻精品动漫 | 香蕉伊人| 高h教授1v1h喂奶 | 亚洲天堂一级 | 黄色一级视频在线观看 | 午夜伦理一区二区 | 奇米影视一区二区 | 久久色播| 蜜臀久久99精品久久久久宅男 | 精品人妻一区二区免费 | av在线免费不卡 | 国产精品久久久一区二区三区 | 日韩3p视频 | 澳门三级 | 久久久无码精品亚洲无少妇 | 亚洲第一二三四区 | 天天干夜操 | 免费播放av| 精品乱码久久久久久中文字幕 | 亚洲在线视频免费观看 | 精品国产污污免费网站入口 | 国产精品人人做人人爽人人添 | 高潮久久久| 天天操天天看 | av第一福利大全导航 | 美女的胸给男人玩视频 | 午夜久久久| 丰满人妻一区二区三区精品高清 | 毛片的网址 | 好吊妞操 | 性xxxx欧美 | 国产在线麻豆精品观看 | 日韩精品久久一区 | 日本特黄一级片 | 久久狠| 欧美激情综合五月色丁香 | 久久久亚洲一区 | 欧美精品videos极品 | 色老大网站 | 亚洲污污视频 | 亚洲精品xxx | 污污视频免费网站 | wwww日本60 | 糖心vlog精品一区二区 | 丰满少妇一区二区三区 | 自拍视频啪 | 九九九九九热 | 国产一区二区三区视频免费在线观看 | 91高清免费| 精品欧美日韩 | 日韩欧美一级在线 | www.久久久久久久久 | wwwjizzzcom| 日韩黄色一区二区 | 日韩精品视频在线观看免费 | 国产中文 | 欧美精品一区二区三区蜜臀 | 日韩男人天堂 | 黄色片xxx | 女女互慰吃奶互揉调教捆绑 | 山村大伦淫第1部分阅读小说 | 国产精品精品软件视频 | 性生活视频在线播放 | 超碰在线日韩 | 亚洲欧美自拍偷拍 | 杂技xxx裸体xxxx欧美 | 日韩人妻精品一区二区三区视频 | 欧美一级特黄aaaaaa大片在线观看 | 欧美爱爱爱 | 一区二区三区视频免费视 | 一区二区免费看 | 亚洲国产中文在线 | 插插影视 | 日韩精品在线免费 | 特级特黄刘亦菲aaa级 |