鏈表

from:http://public.whut.edu.cn/comptsci/web/data/512.htm

 

鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱爲結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。
    由於鏈表這種數據結構必須利用指針變量才能實現,因此先介紹指針的概念。
    由前述可知,計算機的內存儲器被劃分爲一個個的存儲單元,每個存儲單元存放8個二進制位(即一個字節)。存儲單元按一定的規則編號,這個編號就是存儲單元的地址。也就是說計算機中存儲的每個字節是一個基本內存單元,有一個地址。計算機就是通過這種地址編號的方式來管理內存數據讀寫的準確定位的。
    計算機是如何從內存單元中存取數據的呢?從程序設計的角度看,有兩種辦法:一是通過變量名;二是通過地址。程序中聲明的變量是要佔據一定的內存空間的,例如,C語言中整型變量佔2字節,實型變量佔4字節。程序中定義的變量在程序運行時被分配內存空間。在變量分配內存空間的同時,變量名也就成爲了相應內存空間的名稱,在程序中可以用這個名字訪問該內存空間,表現在程序語句中就是通過變量名存取變量內容(這就是程序中定義變量的用途,即程序中通過定義變量來實現數據在內存中的存取)。但是,有時使用變量名不夠方便或者根本沒有變量名可用,這時就可以直接用地址來訪問內存單元。例如,學生公寓中每個學生住一間房,每個學生就相當於一個變量的內容,變量名指定爲學生姓名,房間是存儲單元,房號就是存儲單元地址。如果知道了學生姓名,可以通過這個名字來訪問該學生,這相當於使用變量名訪問數據。如果知道了房號,同樣也可以訪問該學生,這相當於通過地址訪問數據。
    由於通過地址能訪問指定的內存存儲單元,因此可以說,地址“指向”該內存存儲單元(如同說,房間號“指向”某一房間一樣)。故將地址形象化地稱爲“指針”,意思是通過它能找到以它爲地址的內存單元一個變量的地址稱爲該變量的“指針”。如果有一個變量專門用來存放另一個變量的地址(即指針),則它稱爲“指針變量”。在許多高級程序設計語言中有專門用來存放內存單元地址的變量類型,這就是指針類型。指針變量就是具有指針類型的變量,它是用於存放內存單元地址的。
    通過變量名訪問一個變量是直接的,而通過指針訪問一個變量是間接的。就好像要在學生公寓中找一位學生,不知道他的姓名,也不知道他住哪一間房,但是知道101房間裏有他的地址,走進101房間後看到一張字條:“ 找我請到302”,這時按照字條上的地址到302去,便順利地找到了他。這個101房間,就相當於一個指針變量,字條上的字便是指針變量中存放的內容(另一個內存單元的地址),而住在302房間的學生便是指針所指向的內容。
    指針作爲維繫結點的紐帶,可以通過它實現鏈式存儲。假設有五個學生某一門功課的成績分別爲A、B、C、D和E,這五個數據在內存中的存儲單元地址分別爲1248、1488、1366、1022和1520,其鏈表結構如圖5.4所示。

 

         單鏈表
                        
圖5.4鏈表示意圖

    鏈表有一個“頭指針”變量,圖5.4中以 head表示,它存放一個地址,該地址指向鏈表中第一個結點,第一個結點又指向第二個結點……直到最後一個結點。該結點不再指向其他結點,它稱爲“表尾”,它的地址部分存放一個“NULL”(表示“空地址”),鏈表到此結束。鏈表中每個結點都包括兩個部分:用戶需要用的實際數據和下一個結點的地址。
    可以看到鏈表中各結點在內存中可以不是連續存放的。要找到某一結點C,必須先找到其上一個結點B,根據結點B提供的下一個結點地址才能找到C。鏈表有一個“頭指針”,因此通過“頭指針”可以按順序往下找到鏈表中的任一結點,如果不提供“頭指針”,則整個鏈表都無法訪問。鏈表如同一條鐵鏈一樣,一環扣一環,中間是不能斷開的。打個比方,幼兒園的老師帶領孩子出來散步,老師(作爲頭指針)牽着第一個小孩的手,第一個小孩的另一隻手牽着第二個孩子……這就是一個“鏈”,最後一個孩子有一隻手空着,他是“鏈尾”。要找這個隊伍,必須先找到老師,然後按順序找到每一個孩子。
    圖5.4的鏈表每個結點中只有一個指向後繼結點的指針,該鏈表稱爲單鏈表。其實結點中可以有不止一個用於鏈接其他結點的指針。如果每個結點中有兩個用於鏈接其他結點的指針,一個指向前趨結點(稱前趨指針),另一個指向後繼結點(稱後繼指針),則構成雙向鏈表。雙向鏈表如圖5.5所示。

         雙向鏈表

                            圖5.5雙向鏈表示意圖
     雙向鏈表的插入和刪除動態圖:

        雙向鏈表的刪除    

        雙向鏈表的插入

     鏈表的一個重要特點是插入、刪除操作靈活方便,不需移動結點,只需改變結點中指針域的值即可。而數組由於用存儲單元的鄰接性體現數組中元素的邏輯順序關係,因此對數組進行插入和刪除運算時,可能需要移動大量的元素,以保持這種物理和邏輯的一致性。如數組中有m個元素,往第i(i<m)個元素後面插入一個新元素,需要將第i+1個元素至第m個元素共m-i個元素向後移動。
    單向鏈表的插入和刪除動態圖:

      單向鏈表的插入

       單向鏈表的刪除    

    由於鏈表的插入、刪除操作靈活方便,我們可以在程序運行期間根據需
要動態申請內存,爲新結點分配存儲空間,並通過修改指針將新結點鏈接到鏈表上。因此,鏈表是一種動態數據結構。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章