鏈表及數組模擬鏈表


轉載請注明出處,部分內容引自百度百科、譚浩強《C程序設計》、蝸牛君的奮斗史大神的博客



前置知識:    C語言入門



數組黨的福音(本蒟蒻學鏈表時不會指針,然而好像所有人都拿指針寫)
首先,我們需要知道什么是鏈表
百度百科
看不懂勿噴(畢竟百度百科也不是用來讓人看懂的)
我們可以從中得出鏈表的特性:
鏈表是一種物理存儲單元上非連續、非順序的存儲結構
提取主謂賓:鏈表是存儲結構。我認為這就是鏈表的本質——一種數據結構。
那么非連續、非線性有什么含義呢?這表明鏈表的內存是不連續的,前一個元素存儲地址的下一個地址中存儲的不一定是下一個元素。鏈表通過一個指向下一個元素地址的引用將鏈表中的元素串起來。
鏈表分為三類:單向鏈表、雙向鏈表、循環鏈表
1,單向鏈表
單向鏈表是最簡單的鏈表形式。我們將鏈表中最基本的數據稱為節點(node),每一個節點包含了數據塊和指向下一個節點的指針,鏈表有一個頭指針變量,圖中以head表示。可以看出,head指向第一個元素,第一個元素又指向第二個元素……直到最后一個元素,該元素不再指向其他元素,它稱為表尾,它的地址部分為空,鏈表到此結束。

可以看到,要找鏈表中的某一元素,必須先找到上一個元素,根據它提供的下一個元素的地址才能找到下一個元素。如果不提供頭指針,則整個鏈表都無法訪問。鏈表如同一條鐵鏈一樣,一環扣一環,中間是不能斷開的。
為了理解什么是鏈表,打一個通俗的比方:幼兒園的老師帶領孩子們出來散步,老師牽着第一個小孩的手,第一個小孩的另一只手牽着第二個孩子……這就是一個鏈,最后一個孩子有一只手空着,他是鏈尾。要找到這個隊伍,必須先找到老師,然后順序找到每一個孩子。
變量聲明:

const int maxn=1010; struct node{    //point即指針,data就是需要維護的數據
    int point,data; }a[maxn]; int head,cnt;    //head即頭指針,cnt即內存池計數器

建立:

head=++cnt;        //把head設為沒有實際意義的哨兵
a[head].data=0;

插入(插入數據now到第k個元素之后):

add(++k,now);    //進入,因為計算時考慮了哨兵,所以進入時++k
void add(int k,int now) { for(int i=head;i;i=a[i].point)    //從頭指針開始遍歷鏈表
        if(!(--k))        //到達插入位置
 { a[++cnt].point=a[i].point;    //將新插入節點的指針指向插入位置的后繼
            a[i].point=cnt;        //將前驅節點的指針指向新插入節點
            a[cnt].data=now; break; } }


刪除(刪除第k個元素):

del(++k);    //進入
void del(int k) { for(int i=head;i;i=a[i].point) if((--k)==1)    //找到前驅
 { a[i].point=a[a[i].point].point;        //將前驅的指針指向后繼
            break; } }


遍歷鏈表:

for(int i=a[head].point;i;i=a[i].point) cout<<a[i].data<<endl;

2,雙向鏈表
顧名思義,雙向鏈表就是有兩個方向的鏈表。同單向鏈表不同,在雙向鏈表中每一個節點不僅存儲指向下一個節點的指針,而且存儲指向前一個節點的指針。它的優點是訪問、插入、刪除更方便。但“是以空間換時間”。

變量聲明:

struct node{ int pre,nxt,data;    //前驅和后繼
}a[maxn]; int head,cnt;

插入:

void add(int k,int now) { for(int i=head;i;i=a[i].nxt) if(!(--k)) { a[++cnt].nxt=a[i].nxt;    //這兩個和單鏈表一樣
            a[i].nxt=cnt; a[a[cnt].nxt].pre=cnt;    //將后繼的前驅更新為新插入節點
            a[cnt].pre=i;    //將新插入節點的前驅設為其前驅
            a[cnt].data=now; break; } }


刪除:

void del(int k) { for(int i=head;i;i=a[i].nxt) if(!(--k)) { a[a[i].pre].nxt=a[i].nxt; a[a[i].nxt].pre=a[i].pre; break; } }

3,循環鏈表
(1),單向循環鏈表
最后一個節點的指針指向頭結點
(2),雙向循環鏈表
最后一個節點的指針指向頭結點,且頭結點的前驅指向最后一個結點
代碼實現就不再給出,相信大家已經能夠實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM