C語言程式設計 學習筆記 鍊錶

2021-09-01 06:15:20 字數 4030 閱讀 7524

接可變陣列

但如果我們可以使用block,將其都拼接在一起,並不是用上面的方法複製貼上。每乙個block會有乙個單元指向的是下乙個block的位址,這樣就不會有上述的問題了

所以對於乙個單元,它裡面應該分成兩部分:

1.資料

2.下乙個單元的位址(指標)

這樣指向的下乙個資料結構也應是如此。

直到最後乙個單元,儲存的是資料,位址用乙個標記標誌它已經沒有指向下乙個地方了

當然最開始,還需要乙個指標指向第乙個單元的位址,俗稱head

這樣的東西就叫做鍊錶(linklist),每乙個單元叫做節點

定義:

typedef struct _node node;
對於往煉表內加入資料,**實現如下:

#include #include "node.h"

#include using namespace std;

//typedef struct _node node;

int main(int argc, char** argv)

//找到目前鍊錶的末尾,讓其指向p

last->next = p;

} else

} } while(number != -1);

return 0;

}

2.鍊錶的函式在上述do-while函式內的**,實質上就是乙個對鍊錶進行賦值的功能,那麼我們可以將其封裝成乙個函式,這樣更易使用,如:

#include #include "node.h"

#include using namespace std;

//typedef struct _node node;

void add(node* head, int number);

int main(int argc, char** argv)

} while(number != -1);

return 0;

}void add(node* head,int number)

//找到目前鍊錶的末尾,讓其指向p

last->next = p;

} else

}

但這樣有非常嚴重的問題,在add函式中,我的head是乙個傳參,在函式中的head = p;這個操作實質上並沒有任何用,add函式用完後的傳參被釋放,head永遠是null

解決方法

1.將node *head設為全域性變數

缺陷:全域性變數是有害的,是一次性的,這個head只對乙個鍊錶起作用,如果乙個程式有多個鍊錶,全設為全域性變數很危險

2.將add函式設定乙個返回值head,執行完畢後將head的值返回回去

head = add(head, number);
這方法看似不錯,但是在使用的時候感覺會很奇怪(尤其是給他人使用這個方法的時候)——只不過想add值進去,為什麼要返回值呢?要返回也是返回add成功與否吧?

3.傳head的指標回去

那這樣,函式的應該為

void add(node **phead, int number);
但是用到**的時候就要注意,指標的指標是乙個非常複雜的東西,一不小心會產生難以想象的錯誤,且指向指標的指標**也不易於閱讀

4.建立乙個結構體list,裡面存的是node *head,再對其進行使用

函式呼叫的時候是呼叫list的位址,實質上其實是和3是一樣的,但是換了乙個更易閱讀的方式。也就是通過自己定義的資料結構來代表整個list,**:

#include #include "node.h"

#include using namespace std;

//typedef struct _node node;

typedef struct _list list;

void add(list *plist, int number);

int main(int argc, char** argv)

} while(number != -1);

return 0;

}void add(list *plist, int number)

//找到目前鍊錶的末尾,讓其指向p

last->next = p;

} else

}

鍊錶的搜尋遍歷:乙個指標,拿到head,輸出value

變到下乙個位址

當沒有下乙個位址(最後指向的是null)迴圈結束

可以用for,也可以用while,for迴圈更加易懂:

node *p;//開始遍歷

for( p = list.head; p; p = p->next)

cout同樣的,可以封裝成函式,取名為print,我們需要的只是head

void print(list *plist)

cout既然能遍歷了,那麼我想尋找鍊錶中某乙個特定的數那也很方便了

cin>>number;

node *p;

int isfound = 0;

for(p = list.head; p; p->next)

}

但是這樣有乙個問題,q初始值是null,對於如果第乙個單元就是要去掉的,此時我們要修改的是head所指的地方,而不是對q有什麼操作。

在如此情況下,上述**中的q->next是非法、無意義的

所以我們需要通過語句將其保護起來(讓**更加嚴謹)

**實現:

node *q;

for(q = null,p = list.head; p; q=p,p = p->next) else

free(p);

break;

} }

鍊錶的清除每次遍歷到乙個,先有乙個臨時變數儲存next,然後free(),接著到下乙個節點,繼續free,直到p=null結束

for( p = list.head; p; p=q)
程式設計入門-鍊錶到此為止,至此將此課的**全部奉上:

node.h:

#ifndef _node_h_ 

#define _node_h_

typedef struct _node node;

#endif

main.cpp:

#include #include "node.h"

#include using namespace std;

//typedef struct _node node;

typedef struct _list list;

void add(list *plist, int number);

void print(list *plist);

int main(int argc, char** argv)

} while(number != -1);

// print(&list);

cin>>number;//尋找值

node *p;

int isfound = 0;

for(p = list.head; p; p->next) else

free(p);

break;

} }for( p = list.head; p; p=q)

return 0;

}void add(list *plist, int number)

//找到目前鍊錶的末尾,讓其指向p

last->next = p;

} else

} void print(list *plist)

cout<

}

C語言學習筆記 鍊錶

鍊錶是一種常見的重要的資料結構。它是動態地進行儲存分配的一種結構。它可以根據需要開闢記憶體單元。鍊錶有乙個 頭指標 變數,以head表示,它存放乙個位址。該位址指向乙個元素。鍊錶中每乙個元素稱為 結點 每個結點都應包括兩個部分 一為使用者需要用的實際資料,二為下乙個結點的位址。因此,head指向第乙...

C語言學習筆記 24鍊錶

一 鍊錶和陣列的比較 二 鍊錶中的術語 三 演算法 四 鍊錶結構示意圖 五 示例 include include include 定義乙個鍊錶結構 struct node 函式宣告 struct node createlist void void ergodiclist struct node in...

C語言學習筆記 鍊錶(三)鍊錶的插入

從指定節點後方插入新節點 假設我們已有五個節點,我們要把乙個新節點new插入到3後邊。需要三個步驟 找到 3 這個節點。把新節點指向3這個節點的下乙個節點 3 next new next 把3指向新節點。3 next new 定義結構體 struct test 輸出鍊錶資料 void printli...