動態記憶體分配應用舉例(鍊錶)

2021-09-30 06:32:20 字數 2839 閱讀 2431

動態記憶體分配應用舉例(鍊錶)

我們知道,陣列式計算機根據事先定義好的陣列型別與長度自動為其分配一連續的儲存單元,相同陣列的位置和距離都是固定的,也就是說,任何乙個陣列元素的位址都可乙個簡單的公式計算出來,因此這種結構可以有效的對陣列元素進行隨機訪問。但若對陣列元素進行插入和刪除操作,則會引起大量資料的移動,從而使簡單的資料處理變得非常複雜,低效。

為了能有效地解決這些問題,一種稱為「鍊錶」的資料結構得到了廣泛應用。

1. 鍊錶概述

鍊錶是一種動態資料結構,他的特點是用一組任意的儲存單元(可以是連續的,也可以是不連續的)存放資料元素。

鍊錶中每乙個元素成為「結點」,每乙個結點都是由資料域和指標域組成的,每個結點中的指標域指向下乙個結點。head是「頭指標」,表示鍊錶的開始,用來指向第乙個結點,而最後乙個指標的指標域為null(空位址),表示鍊錶的結束。

可以看出鍊錶結構必須利用指標才能實現,即乙個結點中必須包含乙個指標變數,用來存放下乙個結點的位址。

實際上,鍊錶中的每個結點可以用若干個資料和若干個指標。結點中只有乙個指標的鍊錶稱為單鏈表,這是最簡單的鍊錶結構。

再c++中實現乙個單鏈表結構比較簡單。例如,可定義單鏈表結構的最簡單形式如下

struct node

;這裡用到了結構體型別。其中,*next是指標域,用來指向該結點的下乙個結點;data是乙個整形變數,用來存放結點中的資料。當然,data可以是任何資料型別,包括結構體型別或類型別。

在此基礎上,我們在定義乙個鍊錶類list,其中包含鍊錶結點的插入,刪除,輸出等功能的成員函式。

class list

void insertlist(int adate,int bdate);//鍊錶結點的插入

void deletelist(int adate);//鍊錶結點的刪除

void outputlist();//鍊錶結點的輸出

node*gethead()

};2. 鍊錶結點的訪問

由於鍊錶中的各個結點是由指標鏈結在一起的,其儲存單元文筆是連續的,因此,對其中任意結點的位址無法向陣列一樣,用乙個簡單的公式計算出來,進行隨機訪問。只能從鍊錶的頭指標(即head)開始,用乙個指標p先指向第乙個結點,然後根據結點p找到下乙個結點。以此類推,直至找到所要訪問的結點或到最後乙個結點(指標為空)為止。

下面我們給出上述鍊錶的輸出函式;

void list::outputlist()

coutp=head;

if(head==null)  //若是空表,使b作為第乙個結點

else

if(p->data==adate)   //若a是第乙個結點

else

if(p->data==adate)     ///若有結點a

else                    //若沒有結點a;}}

4. 鍊錶結點的刪除

如果要在鍊錶中刪除結點a並釋放被刪除的結點所佔的儲存空間,則需要考慮下列幾種情況。

(1) 若要刪除的結點a是第乙個結點,則把head指向a的下乙個結點。

(2) 若要刪除的結點a存在於鍊錶中,但不是第乙個結點,則應使a得上乙個結點a_k-1的指標域指向a的下乙個結點a_k+1。

(3) 空表或要刪除的結點a不存在,則不做任何改變。

以下是鍊錶類的結點刪除函式。

void list::deletelist(int adate)  //設adate是要刪除的結點a中的資料成員

else

if(p->data==adate)    //若有結點a}}

例題;利用以上三個鍊錶操作成員函式insertlist,deletelist.outputlist,可形成以下的簡單鍊錶操作程式。

#include"iostream.h"

struct node

;class list

void insertlist(int adata,int bdata);

void deletelist(int adata);

void outputlist();

node*gethead()

};void list::insertlist(int adata,int bdata)  //設adata是結點a中的資料,bdata是結點b中的資料

else

if(p->data==adata)   //若a是第乙個結點

else

if(p->data==adata)     ///若有結點a

else                    //若沒有結點a;}}

void list::deletelist(int adata)  //設adata是要刪除的結點a中的資料成員

else

if(p->data==adata)    //若有結點a}}

void list::outputlist()

coutcout<<"/n鍊錶b:";

b.outputlist();

b.deletelist(67);

cout<<"刪除元素67後";

b.outputlist();

}程式執行結果為

鍊錶a;25,41,16,98,5,67,9,55,1,121

刪除元素data[7]後;

25,41,16,98,5,67,9,1,121

鍊錶b;121,1,55,9,67,5,98,16,41,25,

刪除元素67後;

121,1,55,9,5,98,16,41,25,

下面是楊輝三角的**:

#include

#include

using namespace std;

int main()

for(i=3;ifor(i=1;icout

}

動態記憶體分配

在c 中建立乙個物件時,我們必須要為這個物件申請一塊記憶體,而且要用建構函式對這塊記憶體進行初始化。c 中的new和delete相對於c的庫函式malloc和free在這方面有很大的優勢,所以我們主要講的是運算子new和delete。當用new來建立乙個物件時,它會自動在堆裡為物件分配記憶體並且為這...

動態記憶體分配

為什麼使用動態記憶體分配?c語言中的一切操作都是基於記憶體的 變數和陣列都是記憶體的別名,如何分配這些記憶體由編譯器在編譯期間決定 定義陣列的時候必須指定陣列唱的 而陣列長度是在編譯期就必須決定的 需求 程式執行的過程中,可能需要使用一些額外的記憶體空間 malloc和free malloc和fre...

動態記憶體分配

c的儲存類別有4種 自動的 auto 靜態的 statics 暫存器的 register 外部的 extern 全域性變數時分配在記憶體中的靜態儲存區 靜態區域性變數屬於靜態儲存類別,在靜態儲存區內分配儲存單元,是在編譯時賦初值的,只賦初值一次,在程式執行時它已有初值,以後每次呼叫函式時不再重新賦初...