1 、鏈式存儲概念
(1)順序存儲:
我們所學的數組是一種連續的順序存儲方式,知道了數組某一個元素的地址,由於連續,則可以通過地址的計算能夠算出每一個元素的地址。
(2)鏈式存儲:
該方式是每個單元的存儲位置是不連續的,隨機的,但是可以通過在前一個存儲單元中記錄下一個存儲單元的地址來把所有的存儲單元聯繫起來,就像生活中的鏈條一樣一環套一環,每個存儲單元我們叫做節點。
每個節點可以分爲兩部分,數據域和地址域,數據域用來存儲相關數據,地址域用來存儲下一個節點的地址
如下圖:
節點1 地址爲 0x90, 存儲數據1;
節點2 地址爲 0x20,存儲數據2;
節點3 地址爲 0x40,存儲數據3;
節點4 地址爲 0x70,存儲數據4;
通過節點1可以找到節點2的地址,找到節點2的地址就能找到節點3的地址,從而找到節點4的地址,這樣邏輯上的鏈表就建成了。
2、代碼實現模型
(1) 建立模型一
首先定義結構體s_node ,成員有兩個,一個用來存放數據,一個用來存放地址。
tyepdef struct node{
int data;
struct node* next;
}s_node;
int main(int argc,char* argv[])
{
s_node node1,node2,node3,node4;
node1.next = &node2;
node2.next = &node3;
node3.next = &node4;
node4.next = NULL;
return 0;
}
如上代碼其實已經建立了一個鏈表,每個節點的內存在棧中,如果知道了node1的地址,那麼我就可以起知道其他幾個節點的地址,從而訪問所有的節點。
int i = 0;
s_node *p = &node1;
for(i = 0;i<4;i++)
{
p->data = i;
p = p->next;
}
內存圖如下:
(2)建立模型二
所有節點的內存從堆中分配出來,並建立起聯繫:
int main(int argc,char* argv[])
{
s_node *p1,*p2,*p3,*p4;
p1 = (s_node*)malloc(sizeof(s_node));
p2 = (s_node*)malloc(sizeof(s_node));
p3 = (s_node*)malloc(sizeof(s_node));
p4 = (s_node*)malloc(sizeof(s_node));
/*假定malloc都申請成功*/
p1->next = p2;
p2->next = p3;
p3->next = p4;
p4->next = NULL;
//退出前注意free
return 0;
}
訪問如下:
int i = 0;
s_node *p = p1;
for(i = 0;i<4;i++)
{
p->data = i;
p = p->next;
}
內存圖如下:
(3)刪除模型
以 建立模型二 爲基礎,目前有4個指針變量 p1 p2 p3 p4分別存儲了節點1、2、3、4的地址,每個節點都是從堆區分配出來的。
如果要釋放掉節點2,並且要保證刪除節點2後鏈表還是完整的,那麼就要把節點1 與 節點3 連接起來,反應到代碼就是節點1的 next 成員變量要存儲節點3的地址:
p1->next = p3;
free(p2);
在鏈表中刪除某個節點需要能夠訪問這個節點的前一個節點。