資料結構之鍊錶(C 語言描述)

2021-07-23 04:26:16 字數 4081 閱讀 6489

鍊錶,是最基礎的資料結構之一,其儲存空間的不連續性以及便捷的新增節點和刪除節點的優點讓其應用頗廣。今天主要談一談鍊錶的一些基礎也是核心演算法,即鍊錶的增刪改查以及鍊錶反轉(reverse)。

由於用c++描述,我們直接就定義為結點類。如果用單純的c語言的話可以把它換成struct結構體。

class node;
還有兩個成員變數,乙個為int element,用來存放資料,即資料域(當然資料型別可以不光是int,這個可以根據實際需求進行調整)。另外乙個為node *link,即位址域,用來存放下乙個結點的位址。

鍊錶分為單鏈表和雙向鍊錶。

單鏈錶可分為不帶表頭節點的單向鍊錶和帶有表頭節點的單向鍊錶。

我們先來看單鏈表。

結構如下圖所示。first節點稱為頭指標,頭指標是管理單鏈表的基礎。頭指標指向第乙個元素a0所在的節點(頭節點)。弱頭指標為空,則稱此鍊錶為空鍊錶。尾節點沒有後繼,故其link域為null。剩下的每個節點的link域均存放下乙個節點的位址。

(ps: 請大家一定注意區分,頭指標和頭節點)

鍊錶的結構看上去非常簡單,那麼它的基本演算法其實也是十分清晰明了的。

整個鍊錶類(singlelist)的構成

class singlelist

~singlelist()

}bool insert();

bool delete();

bool update();

bool find();

node* reverse();

}

singlelist類共有兩個成員變數。乙個為node* first。用於存放鍊錶的頭指標。另乙個為int length. 用來記錄鍊錶的長度。

1.    建構函式

建構函式沒啥說的。令頭指標為null,length為0.

2.    析構函式

析構函式作用無非是刪除整個鍊錶。那麼肯定是從前往後刪。

~singlelist()

}

初始令p為第二個結點,然後刪除第乙個結點,再讓first指向p, p再變為第三個結點,再刪除第二個結點,再讓first指向p.

以此類推下去,直到把所有的結點都刪除完成。鍊錶的析構工作完成。

3.    查詢(find)

之所以先講查詢,是因為查詢是其他所有操作的基礎。

我們知道鍊錶的存放是不連續的,所以要想查詢到某個結點,必須要從第乙個結點開始找起,直到找到所需要的那個結點。

原理很簡單,無非是逐一比較。直到element相等。如果到最後乙個結點了還沒有找到,那就返回false.

bool find(int element)

p =p->link;

}return false;

}

4.    更新(update)

修改操作就是在查詢的基礎上,增加了一步賦值操作,直接貼出**。

bool update(int index, int newelement)

node *p= first;

for (int i = 0; i < index; i++)

p->element= newelement;

return true;

}

5.    插入(insert)

先來看一下示意圖。

現在要往b結點和c結點之間插入乙個新的結點e。具體操作怎麼做呢?

1)  讓e的link存放c的位址。

2)  讓b的link存放e的位址。

即 e->link=b->link;(b->link即為c的位址)

b->link=e;

細心的同學可能會問,如果我要在鍊錶的最前端插入乙個結點怎麼辦?

其實步驟是一樣的,在表示上略有不同。不過為了清楚起見,我還是放一張圖幫助大家理解。

往a結點(頭節點)之前插入結點e。

1)e->link=first;

2)first=e;

bool insert(int i, int element)

else if (i == -1)

else

q->element= element;

q->link= p->link;

p->link= q;

}length++;

return true;

}

6.    刪除(delete)

刪除操作和插入操作類似。不過為了更加清晰,還是貼出示意圖。依舊是分為兩類,刪除頭節點和刪除非頭節點的其他結點。

先看非頭節點的結點刪除。要刪除b結點。

1)a->link=b->link

2)delete b

再看刪除頭節點。

直接令first=first->link即可。

bool delete(int i)

if (i == 0)

else

node*q = p->link;

p->link= q->link;

delete q;

length--;

}return true;

}

7.    反轉(reverse)

鍊錶的反轉的意思就是將整個鍊錶調個順序,頭節點成為尾結點,尾結點成為頭節點,其他的結點也是如此進行反轉。

那麼有同學就說,反轉不就是依次找到最後乙個結點,然後插入新鍊錶,再刪除舊鍊錶的最後乙個結點,依次遍歷即可。

singlelist reverse()

newsinglelist.insert(i,p->element);

}return newsinglelist;

}

那有沒有更好的方法呢?當然有。下面的這種方法既不會有額外的空間的開銷,時間複雜度也只有o(n).即只需要遍歷一次即可完成目標。

貼出示意圖,我們來逐步分析。

上下兩幅圖進行對比,細心的同學就會發現我們其實並沒有更改他們的位置,只是讓他們所有的link指向了他們的前乙個結點(原來的link是指向後乙個結點的).原理十分簡單,具體怎麼做呢?

我們來思考一下這個問題。要想讓結點的link指向前乙個結點,那我們肯定需要前乙個結點的位置,加上本來指向的後乙個結點,這麼來看,我們要想完成這個工作就要有三個結點來為我們服務。

我們初始化的三個結點不妨設為p,q,r。

首先我們令

p=first;q=p->link;r=q->link;

完成了三個結點的初始化。

接著我們讓q的link指向它的前乙個結點p,即q->link=p;

接著我們挪動p結點和q結點還有r結點,讓他們往後移動乙個位置,讓p結點指向q,q結點指向r,r結點指向下乙個結點。即

p=q;q=r;r=q->link;

接著重複剛才的錯做,讓q->link=p;

接著繼續向後挪動迴圈,直到q結點為空為止。

再最後,我們再讓我們原始的頭節點的link為空(此時它已經變成了尾結點)即

first->link=null;

再重新規定我們的頭節點,即為p.

first=p;

最後返回頭指標first.整個反轉操作完成。

具體**如下:

node *reverse()

first->link= null;

first =p;

return first;

}

C 語言 資料結構之雙向鍊錶

雙向鍊錶的空間結構如下圖所示 int initdlist dlinklist head 初始化雙向迴圈鍊錶 int createdlist dlinklist head,int n 建立雙向迴圈鍊錶 return 1 void printdlist dlinklist head 輸出雙向迴圈鍊錶中的...

C語言資料結構之鍊表篇

線性表的定義 定義n個資料元素的有限序列,記作 a1,a2,an ai 是表中資料元素,n 是表長度 線性表的特點 1.除第乙個元素外,其他每乙個元素有乙個且僅有乙個直接前驅。2.除最後乙個元素外其他每乙個元素有乙個且僅有乙個直接後繼。順序表的定義和特點 定義將線性表中的元素相繼存放在乙個連續的儲存...

C語言 資料結構之雙向鍊錶

本文將實現雙向鍊錶的基礎介面功能 1.初始化 銷毀 2.增刪改查 標頭檔案dlist.h pragma once 資料型別 typedef int dldatatype 結點型別 typedef struct dlistnode dlistnode 雙向鍊錶型別 typedef struct dli...