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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

C语言链表实现

發布時間:2024/4/18 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言链表实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我學數據結構的時候也是感覺很困難,當我學完后我發現了之所以困難時因為我沒有系統的進行學習,而且很多教授都只是注重數據結構思想,而忽略了代碼方面,為此我寫了這些博文給那些試圖自學數據結構的朋友,希望你們少走彎路


我嘗試用最簡單的語言與代碼來描述鏈表,事實上它本身也很簡單

靜態單鏈表實現


下面一部分的討論都將圍繞上面這幅圖片展開,既然是逐步實現,我不考慮在開頭就讓這個單鏈表完美實現,它將只有兩個部分:鏈表的創建&遍歷鏈表輸出

首先我們要知道一些簡單的概念,一個鏈表是由節點構成,而每個節點又是又一個數據域和一個指向下一個節點的指針構成,因此我們可以很容易寫出下面的結構

struct node//節點 {int data;//數據域,這里我們選擇存儲int型struct node *next;//指針域,指向下一個節點,因此被定義為struct *NODE };
然后再認真觀察一下上面的圖會發現似乎還有一個頭指針沒有用(head pointer),頭指針的作用就是在浩瀚的內存中指向這個鏈表的第一個節點,然后我們由第一個節點(通常稱之為頭結點)的next指針指向下面一個,因此很容易就能想到,只要有了頭指針我們就能很容易的對鏈表進行各項操作。

于是我們可以繼續寫代碼了:

int main(){//創建上圖的鏈表node *head;//一個頭指針。用來指向這個鏈表的第一個節點node *f=new node;//對應上圖第一個節點first node,這種奇葩命名法不是我要讓你們學會的,另我使用了new而不是malloc主要是因為惰性node *s=new node;//對應上圖第二個節點second nodenode *t=new node;//對應上圖第三個節點third nodef->data=8;//第一個node的值f->next=s;//第一個節點next指針指向第二個節點s->data=7;//第二個node的值s->next=t;//第二個節點next指針指向第三個節點t->data=9;//第三個節點值t->next=NULL;//從上圖得知第三個節點后沒有節點了,所以指向NULL,通常稱這個節點為尾節點head=f;//頭指針指向第一個節點,至于為什么前面已經說了//打印這個鏈表里面儲存的元素std::cout<<"鏈表數據:"<<"\n";node *print_ptr=head;//為什么這里要new一個print_ptr?因為我們可能還要利用head進行其他操作,如果直接用head進行下面的操作,就意味著head指向的位置已經改變了while(print_ptr!=NULL){std::cout<<print_ptr->data<<"\n";//通過頭結點迭代打印每個節點的值print_ptr=print_ptr->next;//更新,讓當前指針指向下一個節點}//輸出節點的個數,雖然我們已經知道了是3個node *length_ptr=head;//同上面的print_ptrint k=0;while(length_ptr!=NULL){k++;length_ptr=length_ptr->next;}std::cout<<"鏈表節點個數:"<<"\n"<<k<<"\n";//插入一個節點,這里我選擇在第一個節點與第二個節點之間插入一個新節點ins_nodenode *ins_node=new node;//為即將插入的節點從堆上分配點內存ins_node->data=14;//賦值ins_node->next=s;//讓新節點的next指向第二個節點f->next=ins_node;//然后讓第一個節點的next指向新節點,這就完成了插入//刪除之前插入的節點ins_node=f->next;//讓第一個節點next指向新插入的節點,這里你可能會感到疑惑,我建議你畫圖或者再看看上面的圖就能理解,當然你也可以看下面f->next=ins_node->next;//第一個節點的next指向新節點的next,因為新節點的next相當于指向了第二個節點,所以這里也等價于第一個節點指向第二個節點f->next=f-next->nextsystem("pause"); } 上面就完成了使用尾插法創建的一個鏈表及其簡單操作包括創建/輸出/插入/刪除,不過如你所見它也存在許多不足,比如命名的拙計,new后沒有delete,以及全部在main中執行沒有考慮使用函數等等缺陷,不過這沒關系,因為我們會一步步修改最終讓他成為一個不錯的鏈表


可能你關于上面插入與刪除你沒有搞清楚,這里我再特意講一下


上圖我們需要把儲存14這個數據的node插入到一和二之間,于是我們就需要更改next指針,所以之前f->next=s;就不能用了,


你可能會想到讓第一個指向新節點,然后再讓新節點指向第三個,如:

f->next=ins_node; ins_node->next=f->next;
事實通常證明第一感覺是錯誤的,仔細看看上面代碼你就會發現加入f->next=ins_node,那么第二條就相當于ins_node->next=ins_node;它指向了自己!所以我們需要反過來思考,先讓新節點指向第二個,然后再讓第一個指向新節點,就如上面的代碼了,至于刪除我沒有弄出圖片,我只是簡單講一下,刪除是直接讓第一個節點的next指向需要刪除的節點,然后再讓第一個節點的next指向需要刪除的節點的next,你可能會思考為什么不直接讓第一個節點next指向第二個呢?這個疑問你可以自己解答比較好

動態單鏈表實現

到這里一個簡單的鏈表就已經實現了,但是我們還需要繼續改進,因為我們有時候不知道每個節點儲存的數據,所以我們就需要一個動態鏈表了,下面這個將實現把用戶輸入的數據以鏈式結構儲存,也就是動態鏈表


#include <iostream>struct node {int data;struct node *next; };node *create_linklist(); void print_linklist(node *head);node *create_linklist(){node *head=new node;node *new_node,*current;//一個新節點作為當前節點current=head;//頭結點復制給當前節點int k;printf("輸入節點個數:");scanf("%d",&k);for (int i = 0; i < k; ++i){new_node=new node;if(i==0)//這里也就是創建第一個節點的情況{head=new_node;//把頭指針指向第一個節點}printf("輸入節點數據:");scanf("%d",&new_node->data);current->next=new_node;//注意這里由于創建了一個新節點,而當前節點還是開始的head的那個位置,所以就需要更新一下,讓當前節點next等于new_node的位置new_node->next=NULL;//當前節點的next=NULL表示當前節點就是最后一個節點了current=new_node;//然后把new_node節點復制給當前節點,以便繼續后面的節點添加}return head; }void print_linklist(node *head)//參數傳入一個頭指針用來指向第一個節點 {node *phead=head;while(phead!=NULL){printf("%d", phead->data);phead=phead->next;} }int main(){node *h=create_linklist();print_linklist(h);system("pause"); }

雙向鏈表實現

再想想上面圖片,下面要介紹的就是雙向鏈表,雙向鏈表與單項鏈表的區別就在于它有一個指向前一個節點的指針,于是我們就應該定義這樣的結構體
typedef struct NODE {int data;struct NODE *next;struct NODE *pre; }node;由于雙向鏈表不可避免有些操作需要從后向前遍歷,于是我們就應該添加一個概念,尾指針,也就是指向尾節點的指針,如下就實現了一個雙向鏈表,它有三個節點abc,并有兩種輸出方式 #include <iostream>typedef struct NODE {int data;struct NODE *next;struct NODE *pre; }node;int main(){node *a=new node,*b=new node,*c=new node;node *head=a;node *tail=c;a->data=9;a->next=b;a->pre=NULL;b->data=17;b->next=c;b->pre=a;c->data=6;c->next=NULL;c->pre=b;//輸出/*node *print_head=head;while(print_head!=NULL){std::cout<<print_head->data<<"\n";print_head=print_head->next;}*//*node *print_head=tail;while(print_head!=NULL){std::cout<<print_head->data<<"\n";print_head=print_head->pre;}*/system("pause"); }

雙向鏈表的難點不是創建輸出而是插入與刪除,我沒有制作圖片,所以這需要讀者認真去思考一下,建議畫圖,也很容易理解,下面代碼是在上面創建了abc的基礎上實現的在ab間插入一個k,然后再刪除它

//插入node *k=new node;k->data=698;k->pre=a;k->next=a->next;k->next->pre=a;a->next=k;//刪除k->pre->next=k->next;k->next->pre=k->pre;

循環單鏈表

循環鏈表我不考慮講,因為它就是把尾巴節點指向了頭節點從而形成一個環,所以說循環鏈表不叫loop linked list而叫circular linked list

總結

以上是生活随笔為你收集整理的C语言链表实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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