Lumxi的學習筆記(C語言鍊錶部分)

2021-10-09 22:53:14 字數 4921 閱讀 6216

一.知識回顧

首先在我們宣告結構體的時候,有時候為了方便傳遞結構體,可以採用將結構體的變數進行指標賦值的方式進行

比如

struct student

;struct student stud;

//定義結構體普通變數

struct student *p;

//定義結構體指標變數,表明是同個型別

p=&stud;

那麼在後續的使用中可以採用這種方式

//指標變數名->成員變數名

//如上,p是指標變數名,裡面有id、name、score等成員變數名

p->id=lumxi;

//這樣就完成了這個賦值

//而且對於記憶體的分配是節約的

補充函式:

malloc&free

(1)malloc函式是向系統申請乙個長度為size的連續記憶體空間,函式的返回值是記憶體空間的起始位址,如果未能正常分配到記憶體空間,那麼將會返回null,函式用法

(

int*

)malloc

(xx)

//這裡代表的是(int*)表示的是所代表的資料型別

//xx內表示的是所需要的記憶體的大小

//注意需要多少是可以計算的

//比如int是四個位元組,那麼後面輸入的數字即為xx*4個記憶體大小

free函式

free函式是malloc的配套函式,每當我們申請到了一塊記憶體空間,那麼我們在使用完了這個資料之後,需要對這個申請到的記憶體空間進行釋放,以便我們大程式後續的執行

用法

free

(void

*p)//注意free的是乙個指標變數,用來指標那一塊連續的記憶體空間

(2)calloc&realloc函式

作用是向計算機申請分配n個長度為size的連續記憶體空間,函式的返回值是記憶體空間的起始位址。

void

*calloc

(unsigned

int n,

unsigned

int size)

;//用法與malloc類似的

realloc函式

作用是對malloc或者calloc申請到的空間進行重新分配,通常是為了改變原來申請記憶體空間的大小,引數p指向原來分配的空間,size表示重新分配的記憶體大小

void

*realloc

(void

*p,unsigned

int size)

;

上面四個函式的引數和返回值使用了"void *"指標型別,該指標型別的指標變數只儲存乙個純位址,即只表示記憶體位址的編號,而不表示位址的型別,void型別指標與其他型別指標相互賦值的時候,無需強制型別轉換,編譯器會自動進行轉換,但習慣上,void指標賦值給其他型別指標的時候,要使用對應的型別強制轉化

注:這裡搞清楚 *是取內容運算子,可以把後續的那個指標變數所對應的值拿出來用!同時也用在指明指標型別上.

二.鍊錶及其衍生概念

鍊錶:鍊錶是一種常見的資料結構,可以儲存多個同型別的資料,它是動態地進行儲存分配的一種資料結構,因此鍊錶沒有使用陣列時的限制,它可以隨著元素的變化而改變儲存空間,從而節約空間,而且根據malloc的特點,他所申請的記憶體可以是不連續的

結點:結點是鍊錶的基本儲存單位,乙個幾點對應鍊錶中的乙個資料元素,所有的結點具有相同的資料結構,每個節點占用一段連續的記憶體空間,而結點之間可以使用指標鏈結在一起,使用指標乙個元素單位指向另外乙個元素單位,所以稱為鍊錶

資料域:存放資料的結點

指標域:用來存放下個結點的位址

一般形式如:

struct node

;

那麼在上面這種鍊錶的建立過程中,需要注意以下問題 :

(1)需要定義乙個指標變數指向第乙個結點,這個結點稱為頭結點,值得注意的是,第乙個指標可以為null,即空指標,亦或者是直接包含有乙個資料域

(2)除最後乙個結點外,其他結點的指標域指向下乙個指點

(3)最後乙個結點的指標域用來存放null,表示結束

(4)結點的資料域可以定義多個資料成員,即可以再次定義乙個結構

這種鍊錶結構稱為單向鍊錶結構,查詢只能按照順序操作.

三.鍊錶的基本操作(建立、插入與刪除、遍歷鍊錶)

(1)定義鍊錶結點的型別

程式中如果使用鍊錶,首先要定義描述鍊錶結點的結構體型別

struct product

;

(2)建立乙個鍊錶

node *

create()

//建立鍊錶

else

tail=p;

//指標的賦值,即tail繼續指向新的結尾點

printf

("請輸入商品的編號和**(如果輸入編號為0,那麼表示結束\n");

scanf

("%d%lf"

,&id,

&price);}

return head;

//返回值是鍊錶的頭指標

}

具體建表如上,在這裡進行註解說明

1.p指向鍊錶建立過程中新增加的結點

2.迴圈中每次建立乙個新結點並鏈結到鏈結尾部後,那麼tali就不再是尾結點,而需要讓tail指向新的尾結點

3.函式create在main中呼叫方法如下

node *head;

head=

create()

;

(3)鍊錶的遍歷

具體過程是指:從鍊錶的第乙個結點開始,依次對鍊錶中的每乙個結點進行一次訪問,直到鍊錶結束為止,遍歷鍊錶使用迴圈結構來實現,首先使指標p指向第乙個結點,通過p對結點進行訪問,訪問完成後,使指標p指向指向下乙個結點,如此不斷迴圈,直到鍊錶結束(p為null)

我們一般會進行如下操作:輸出結點的資料域、修改結點的資料域、對結點進行計數、對結點資料進行判斷.

輸出鍊錶所有結點的函式display

void

display

(node *h)

printf

("---------------------\n");

}

如下為display的實現總結

1.函式的引數h表示的是要輸出的鍊錶的頭指標

2.指標p指向第乙個結點

3.在main中呼叫的方法應該是display(head)

同理,我們可以實現鍊錶結點的統計

}

intcount

(node *h)

return n;

}

同理,在main中呼叫應該是count (head)

(4)在鍊錶中查詢結點

node *

search_for

(node *h,

int id)

return p;

}

使用方法為p=search_for(head,xx)

(5)鍊錶結點的插入

插入的演算法如下:

1.在鍊錶中找到插入點,這個插入點是相鄰結點中前面的結點,尋找插入點通常使用迴圈語句來實現。

在找到插入點後,使得指標p指向該結點,然後準備好插入的新結點c,使指標指向新結點

2.使得新結點c稱為結點b的前驅結點.

q->next=p->next;

3.將c變成a的後續結點

p->next=q;

node *

insert

(node *h,

int n,

int id,

double price)

p=h;

for(j=

0;j>next!=

null

;j++

)//迴圈找第n個結點

//迴圈結束後,如果有第n個結點,則p指向該結點,否則,指向最後乙個結點

//插入新結點s

s->next=p-

>next;

p->next=s;

return h;

}

在main中的呼叫方法:head=insert(head,5,1009,120.99)

(6)鍊錶結點的刪除

基本思路如:

1.在刪除結點之前,需要用迴圈結構找到被刪除的那個節點,找到後,用乙個指標q指向它,進行刪除操作時,不僅需要找到被刪除的是哪個結點,還要需要它的前驅結點是哪乙個結點,

2.把要刪除的結點,下面稱為結點b,把結點b拆解出來,只需要讓結點b的前驅結點a的指標域指向結點b的後續結點c即可。

p->next=q->next

b拆解了之後需要釋放記憶體

node *

del(node *h,

int n)

//下面分兩種不同情況進行結點的刪除

if(p==

null

)//沒有第n個結點,不刪除,直接返回原位址

else

if(p==h)

//要刪除的p指向第乙個結點

else

//要刪除的p指向其他結點,pre指向前驅節點

free

(p);

return h;

}

Lumxi的學習筆記 檔案部分

格式化的輸入和輸出 printf flags width prec hil type scanf flags type 註解 1.flags 其意思為標誌,可以加以下幾種字元 左對齊 在前面放個加號或者減號 space 正數留空 0 用0填充 2.width或prec number 最小字元數 下乙...

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

接可變陣列 但如果我們可以使用block,將其都拼接在一起,並不是用上面的方法複製貼上。每乙個block會有乙個單元指向的是下乙個block的位址,這樣就不會有上述的問題了 所以對於乙個單元,它裡面應該分成兩部分 1.資料 2.下乙個單元的位址 指標 這樣指向的下乙個資料結構也應是如此。直到最後乙個...

C語言學習筆記 鍊錶

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