我們知道,陣列式計算機根據事先定義好的陣列型別與長度自動為其分配一連續的儲存單元,相同陣列的位置和距離都是固定的,也就是說,任何乙個陣列元素的位址都可乙個簡單的公式計算出來,因此這種結構可以有效的對陣列元素進行隨機訪問。但若對陣列元素進行插入和刪除操作,則會引起大量資料的移動,從而使簡單的資料處理變得非常複雜,低效。
為了能有效地解決這些問題,一種稱為「鍊錶」的資料結構得到了廣泛應用。
1、概述
鍊錶是一種動態資料結構,他的特點是用一組任意的儲存單元(可以是連續的,也可以是不連續的)存放資料元素。
鍊錶中每乙個元素成為「結點」,每乙個結點都是由資料域和指標域組成的,每個結點中的指標域指向下乙個結點。head是「頭指標」,表示鍊錶的開始,用來指向第乙個結點,而最後乙個指標的指標域為null(空位址),表示鍊錶的結束。
實際上,鍊錶中的每個結點可以用若干個資料和若干個指標。結點中只有乙個指標的鍊錶稱為單鏈表,這是最簡單的鍊錶結構。
再c++中實現乙個單鏈表結構比較簡單。例如,可定義單鏈表結構的最簡單形式如下:
1struct
node;
這裡用到了結構體型別。其中,*next是指標域,用來指向該結點的下乙個結點;data是乙個整形變數,用來存放結點中的資料。當然,data可以是任何資料型別,包括結構體型別或類型別。
在此基礎上,我們在定義乙個鍊錶類clist,其中包含鍊錶結點的插入,刪除,輸出等功能的成員函式。
1//鍊錶類
2class
clist
6void insertlist(int adata, int bdata);//
鍊錶結點的插入:在結點a之前插入結點b
7void deletelist(int adata);//
鍊錶結點的刪除
8void outputlist();//
鍊錶結點的輸出
9 node* gethead() //
獲取頭結點
1011 };
2、鍊錶結點的訪問
由於鍊錶中的各個結點是由指標鏈結在一起的,其儲存單元未必是連續的,因此,對其中任意結點的位址無法向陣列一樣,用乙個簡單的公式計算出來,進行隨機訪問。只能從鍊錶的頭指標(即head)開始,用乙個指標p先指向第乙個結點,然後根據結點p找到下乙個結點。以此類推,直至找到所要訪問的結點或到最後乙個結點(指標為空)為止。
3. 鍊錶結點的插入
如果要在鍊錶中的結點a之前插入結點b,則需要考慮下面幾點情況。
(1) 插入前煉表是乙個空表,這時插入新結點b後。
(2) 若a是鍊錶的第乙個結點,則插入後,結點b為第乙個結點。
(3) 若煉表中存在a,且不是第乙個結點,則首先要找出a的上乙個結點a_k,然後使a_k的指標域指向b,在令b的指標域指向a,即可完成插入。
(4) 如鍊表中不存在a,則插在最後。先找到鍊錶的最後乙個結點a_n,然後使a_n的指標域指向結點b,而b指標的指標為空。
4. 鍊錶結點的刪除
如果要在鍊錶中刪除結點a並釋放被刪除的結點所佔的儲存空間,則需要考慮下列幾種情況。
(1) 若要刪除的結點a是第乙個結點,則把head指向a的下乙個結點。
(2) 若要刪除的結點a存在於鍊錶中,但不是第乙個結點,則應使a得上乙個結點a_k-1的指標域指向a的下乙個結點a_k+1。
(3) 空表或要刪除的結點a不存在,則不做任何改變。
1 #include 2using
namespace
std;
3struct
node;89
//鍊錶類
10class
clist
14void insertlist(int adata, int bdata);//
鍊錶結點的插入:在結點a之前插入結點b
15void deletelist(int adata);//
鍊錶結點的刪除
16void outputlist();//
鍊錶結點的輸出
17 node* gethead() //
獲取頭結點
1819
};20
21/*
22注意:
23由於鍊錶中的各個結點是由指標鏈結在一起的,其儲存單元文筆是連續的,
24因此,對其中任意結點的位址無法向陣列一樣,用乙個簡單的公式計算出來,
25進行隨機訪問。只能從鍊錶的頭指標(即head)開始,
26用乙個指標p先指向第乙個結點,然後根據結點p找到下乙個結點。
27以此類推,直至找到所要訪問的結點或到最後乙個結點(指標為空)為止
28*/
2930
/*31
函式:void clist::insertlist(int adata, int bdata)
32功能:在鍊錶中的結點a之前出入結點b;
33注意事項:
34如果要在鍊錶中的結點a之前插入結點b,則需要考慮下面幾點情況。
35(1) 插入前煉表是乙個空表,這時插入新結點b後。
36(2) 若a是鍊錶的第乙個結點,則插入後,結點b為第乙個結點。
37(3) 若煉表中存在a,且不是第乙個結點,則首先要找出a的上乙個結點a_k,然後使a_k的指標域指向b,在令b的指標域指向a,即可完成插入。
38(4) 如鍊表中不存在a,則插在最後。先找到鍊錶的最後乙個結點a_n,然後使a_n的指標域指向結點b,而b指標的指標為空。
39*/
40void clist::insertlist(int adata, int
bdata)
4152
else
if (p->data == adata)//
若a是第乙個結點
5357
else
5864
if (p->data == adata) //
若有結點a
6569
else
//若煉表中不存在a,則插在最後
7074}75
}7677/*
78函式:
79功能:刪除結點a並釋放被刪除的結點所佔的儲存空間
80注意事項:
81如果要在鍊錶中刪除結點a並釋放被刪除的結點所佔的儲存空間,則需要考慮下列幾種情況。
82(1) 若要刪除的結點a是第乙個結點,則把head指向a的下乙個結點。
8384
(3) 空表或要刪除的結點a不存在,則不做任何改變。
85*/
86void clist::deletelist(int adata) //
設adata是要刪除的結點a中的資料成員
8798
else
99105
if (p->data == adata)//
若有結點a
106110
}111
}112
void
clist::outputlist()
113120 cout <121}
122int
main()
123;
126 a.insertlist(0, data[0]); //
建立鍊錶a首結點
127for (int i = 1; i<10; i++)
128 a.insertlist(0, data[i]); //
順序向後插入
129 cout << "
\n鍊錶a:
"<130a.outputlist();
131 a.deletelist(data[7
]);132 cout << "
刪除元素data[7]後:
"<133a.outputlist();
134 b.insertlist(0, data[0]); //
建立鍊錶b首結點
135for (int i = 0; i<10; i++)
136 b.insertlist(b.gethead()->data, data[i]); //
在首結點處順序向後插入
137 cout << "
\n鍊錶b:
"<138b.outputlist();
139 b.deletelist(67
);140 cout << "
刪除元素67後:
"<141b.outputlist();
142143
return0;
144 }
單鏈表的實現
include includetypedef struct node 定義鍊錶 snode snode creat 建立鍊錶的函式 q next null return head int length snode head 測鍊錶的結點數 return i void display snode he...
單鏈表的實現
單鏈表夜市線性表的一種表現形式,乙個表節點由乙個資料空間和乙個指標域組成。指標域記錄下乙個結點的位址。鍊錶在插入,刪除功能中效率高。但是讀取某個結點的時候需要順序讀取。效率不如順序儲存形式。下面是一些鍊錶實現的 鍊錶.cpp 定義控制台應用程式的入口點。include stdafx.h define...
單鏈表的實現
單鏈表是資料結構中重要並且基礎的一環,學習資料結構就需要知道單鏈表有的常用操作。1 單鏈表的頭插式建立 2 單鏈表的尾插式建立 3 單鏈表的長度計算 4 單鏈表的列印輸出 5 單鏈表的釋放操作 6 單鏈表是否為空判斷 7 單鏈表在指定index插入指定元素 8 單鏈表刪除指定index的節點 9 單...