資料結構 C語言鍊錶實現

2021-08-14 01:51:20 字數 4028 閱讀 1232

[資料結構]c語言鍊錶實現

目錄

靜態單鏈表實現

動態單鏈表實現

雙向鍊錶實現

迴圈單鏈表

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

我嘗試用最簡單的語言與**來描述鍊錶,事實上它本身也很簡單

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

首先我們要知道一些簡單的概念,乙個鍊錶是由節點構成,而每個節點又是又乙個資料域和乙個指向下乙個節點的指標構成,因此我們可以很容易寫出下面的結構

[cpp]

view plain

copy

print?

struct

node

//節點

;  

然後再認真觀察一下上面的圖會發現似乎還有乙個頭指標沒有用(head pointer),頭指標的作用就是在浩瀚的記憶體中指向這個鍊錶的第乙個節點,然後我們由第乙個節點(通常稱之為頭結點)的next指標指向下面乙個,因此很容易就能想到,只要有了頭指標我們就能很容易的對鍊錶進行各項操作。

於是我們可以繼續寫**了:

[cpp]

view plain

copy

print?

intmain()  

//輸出節點的個數,雖然我們已經知道了是3個

node *length_ptr=head;//同上面的

print_ptrint k=0;  

while

(length_ptr!=null)  

std::cout<

<<

"\n"

;//插入乙個節點,這裡我選擇在第乙個節點與第二個節點之間插入乙個新節點ins_node

node *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->next

system("pause"

);  

}  

上面就完成了使用尾插法建立的乙個鍊錶及其簡單操作包括建立/輸出/插入/刪除,不過如你所見它也存在許多不足,比如命名的拙計,new後沒有delete,以及全部在main中執行沒有考慮使用函式等等缺陷,不過這沒關係,因為我們會一步步修改最終讓他成為乙個不錯的鍊錶

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

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

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

[cpp]

view plain

copy

print?

f->next=ins_node;  

ins_node->next=f->next;  

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

到這裡乙個簡單的鍊錶就已經實現了,但是我們還需要繼續改進,因為我們有時候不知道每個節點儲存的資料,所以我們就需要乙個動態鍊錶了,下面這個將實現把使用者輸入的資料以鏈式結構儲存,也就是動態鍊錶

[cpp]

view plain

copy

print?

#include 

struct

node  

;  node *create_linklist();  

void

print_linklist(node *head);  

node *create_linklist()  

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)

//引數傳入乙個頭指標用來指向第乙個節點

}  intmain()  

再想想上面,下面要介紹的就是雙向鍊錶,雙向鍊錶與單項鍊表的區別就在於它有乙個指向前乙個節點的指標,於是我們就應該定義這樣的結構體

[cpp]

view plain

copy

print?

typedef

struct

node  

node;  

由於雙向鍊錶不可避免有些操作需要從後向前遍歷,於是我們就應該新增乙個概念,尾指標,也就是指向尾節點的指標,如下就實現了乙個雙向鍊錶,它有三個節點abc,並有兩種輸出方式

[cpp]

view plain

copy

print?

#include 

typedef

struct

node  

node;  

intmain()*/

/*node *print_head=tail;

while(print_head!=null)*/

system("pause"

);  

}  

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

[cpp]

view plain

copy

print?

//插入

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語言實現 線性鍊錶

declaration.h ifndef declaration h included define declaration h included define true 1 define false 0 define ok 1 define error 0 define infeasible 1 ...

資料結構 迴圈鍊錶 C語言程式實現

這個程式是資料結構中的迴圈鍊錶,題目 設有乙個迴圈鍊錶,其結點值均為正整數,且按絕對值從小到大鏈結。試寫出乙個演算法,將此迴圈鍊錶中的結點按值從小到大鏈結。首先定義標頭檔案 include 輸入輸出等系統函式在這個標頭檔案中 include 標準庫標頭檔案 定義結構體 typedef struct ...

資料結構 鍊錶(純c語言實現)

include include typedef struct nodelnode,linklist linklist greatlinklist int n return list 實現鍊錶的插入操作。1 前驅結點不用找,前驅結點是作為函式的引數的,用來搞清要插入的結點的位置。2 將前驅結點的指標域...