線性表,線性表和鏈表的區別


存儲類別

順序存儲結構 單鏈表
存儲分配方式 用一段連續的存儲單元依次存儲線性表的數據元素 采用鏈式存儲結構,用一組任意的存儲單元存放線性表的元素
時間性能 查找O(1)、插入和刪除O(n) 查找O(n)、插入和刪除O(1)
空間性能 需要預分配存儲空間,分大了浪費,小了容易發生上溢 不需要分配存儲空間,只要有就可以分配,元素個數不受限制

 

通過上面的對比,可以得出一些經驗性的結論:

  • 若線性表需要頻繁查找,很少進行插入和刪除操作時,宜采用順序存儲結構。若需要頻繁插入和刪除時,宜采用單鏈表結構。
  • 當線性表中的元素個數變化較大或者根本不知道有多大時,最好用單鏈表結構,這樣可以不需要考慮存儲空間的大小問題。而如果事先知道線性表的大致長度,用順序存儲結構效率會高很多。

 

http://zhidao.baidu.com/question/237262292.html?si=10&qbpn=1_10&tx=&wtp=wk&word=%E7%BA%BF%E6%80%A7%E8%A1%A8%E5%92%8C%E9%93%BE%E8%A1%A8%E7%9A%84%E5%8C%BA%E5%88%AB&fr=solved&from=qb&ssid=&uid=bd_1424171539_897&pu=sz%40224_240%2Cos%40&step=18&bd_page_type=1&init=middle

線性表、包括順序表和鏈表
順序表里面元素的地址是連續的,
鏈表里面節點的地址不是連續的,是通過指針連起來的。

http://www.bkjia.com/Javabc/1125496.html

簡介

 
         

      一種邏輯結構,相同數據類型的n個數據元素的有限序列,除第一個元素外,每個元素有且僅有一個直接前驅,除最后一個元素外,每個元素有且僅有一個直接后繼。

 
         

線性表的特點:

 
         

(1)元素個數有限    (2)邏輯上元素有先后次序

 
         

(3)數據類型相同    (4)僅討論元素間的邏輯關系

 
         

注:線性表是邏輯結構,順序表和鏈表是存儲結構。

 
         

 
         

1.順序存儲

 
         

順序表,使用數組實現,一組地址連續的存儲單元,數組大小有兩種方式指定,一是靜態分配,二是動態擴展。

 
         

注:線性表從1開始,而數組從0開始。

 
         

優點:隨機訪問特性,查找O(1)時間,存儲密度高;邏輯上相鄰的元素,物理上也相鄰;

 
         

缺點:插入刪除需移動大量元素。

 
         

順序表相關的操作跟數組有關,一般都是移動數組元素。

 
         

這里說一下插入和刪除時的邊界條件,首先線性表從1開始,數組從0開始,單純的文件說明不夠直接,來看圖說話吧。

 
         

 
         

插入時:對於線性表來說最小能插入的位置是1,最大能插入的位置是8(=7+1),所以  1<= index <=(7+1);移動數組元素時要注意,for (int i = count; i >= index; i--) {  items[i] = items[i-1];}

 
         

刪除時:只能在藍色方塊之間尋找節點刪除,即1 <= index <= 7。移動元素,for (i = index; i < count; i++) { items[i-1] = items[i];}

 
         

2.鏈式存儲

 
         

鏈表的定義是遞歸的,它或者為空null,或者指向另一個節點node的引用,這個節點含有下一個節點或鏈表的引用。

 
         

與順序存儲相比,允許存儲空間不連續,插入刪除時不需要移動大量的元素,只需修改指針即可,但查找某個元素,只能從頭遍歷整個鏈表。

 
         

Java中使用嵌套類來定義節點的抽象數據類型:

 
         

 

 
         
private class Node{
    // 鏈表節點的嵌套類
    T item; // 節點內容
    Node next; // 后繼節點
}
 
         

 

 
         

 
         

 

 
         

2.1 單鏈表

 
         

使用任意存儲單元來存儲線性表中的數據元素,節點類型如上。

 
         

單鏈表分為帶頭結點和不帶頭結點兩種,不管有沒有頭結點,頭指針都指向鏈表的第一個節點(有頭結點指向頭結點)。

 
         

頭結點:數值域可不設任何信息,頭結點的指針域指向鏈表的第一個元素。

 
         

帶頭節點的好處有:

 
         

(1)鏈表第一位置節點上的操作和其它位置上的操作一致

 
         

(2)無論鏈表是否為空,頭指針都指向頭結點(非空),空表和非空表處理一樣

 
         

(這里我沒有使用頭結點)

 
         

注:鏈表麻煩的地方是插入和刪除時指針的修改,保證不斷鏈,一般先斷后鏈。

 
         

 
         

基本操作

 
         

1. 頭插法

 
         

將新節點插入到當前鏈表的表頭,(頭結點之后),插入的順序與鏈表中的順序相反,關鍵點就是記住舊的表頭,生成一個新的放到舊表頭前面,如圖:

 
         

 
         
核心代碼:
public void headInsert(T item) {
    Node old = first;
    first = new Node();
    first.item = item;
    first.next = old;
    count++;
}
 
         

2. 尾插法

 
         

增加一個尾指針,新節點插到鏈表的尾部,插入的順序和鏈表的順序一致,如圖:

 
         

 
         
核心代碼:
public void tailInsert(T item) {
    Node old = last;
    last = new Node();
    last.item = item;
    last.next = null;
    if (isEmpty()) {
        first = last;
    } else {
        old.next = last;
    }
    count++;
}
 
         

節點的插入和刪除,要點是先斷后連,關鍵就是不要斷鏈了,以插入為例(把s插入p和q之間),先斷意思是先把p->q斷了,變成s->q,后連,最后再把p和s連接起來。

 
         

3. 插入節點

 
         

待插入節點為s,一般采用后插法,即先找到插入位置節點的前驅節點,然后插入,時間復雜度O(n)。

 
         

 
         
核心代碼為:
p=getNodeByIndex(i-1);
s.next = p.next;
p.next = s;
 
         

還有一種方法是,直接插入到位置的后面(前插法),然后交換兩個節點的值,插入的節點到了指定位置,時間復雜度O(1):

 
         
核心代碼:
s.next = p.next;
p.next = s;
temp = p.item;    // 交換內容
p.item = s.item;
s.item = temp;
 
         

4. 刪除節點

 
         

待刪除節點為q,也是先找到前驅節點,修改指針域即可,時間復雜度O(n)。

 
         

 
         
核心代碼:
P = getNodeByIndex(i-1);
q = p.next;
p.next = q.next;
q = null;
 
         

刪除節點也能直接刪除其后繼節點,然后將后繼節點的內容賦給自己即可,時間復雜度為O(1):

 
         
核心代碼:
q = p.next;
p.item = p.next.item;
p.next = q.next;
q = null;
 
         

2.2 雙鏈表

 
         

單鏈表節點的缺點是只有一個后繼節點,訪問前驅節點只能從頭遍歷(如插入、刪除),時間復雜度為O(n)。雙鏈表,即添加一個指向前驅的節點,節點類型如下:

 
         
private class Node{
    // 鏈表節點的嵌套類
    T item; // 節點內容
    Node prior, next; // 前驅節點和后繼節點
}
 
         

 
         

雙鏈表的查找和單鏈表的相同再次不在贅述,雙鏈表的構造也分為頭插和尾插,與單鏈表唯一不同的是修改前驅指針prior,具體見源碼。插入和刪除時不同,因為需要修改兩個指針,如果給定要操作的節點,插入和刪除的時間復雜度為O(1)。

 
         

注:插入刪除操作同樣也是先斷后連。

 
         

1. 插入節點

 
         

在p節點后插入s節點,先斷后連,先把p和原后繼節點的鏈條給斷了,使后繼節點只跟s節點有關:

 
         

 
         
①s.next = p.next; // 先斷了p的后繼
②p.next.prior = s; // 在斷了p后繼的前驅
③s.prior = p; // 讓s的前驅指向p
④p.next = s; // p的后繼指向s,重新連接上鏈條,此步必須在①②之后
 
         

2. 刪除節點

 
         

刪除節點p的后繼節點q,也是先斷后連,把q和其后繼節點的關系,轉讓給p即可:

 
         

 
         
①p.next = q.next; // 先斷了q的后繼
②q.next.prior = p; // 在斷了q后繼的前驅

刪除節點q的前驅節點p,把p和去前驅節點的關系轉讓給q即可:
①q = p.prior.next; // 把p前驅節點的后繼改成q
②q.prior = p.prior; // 把q的前驅節點改成p的前驅節點
 
         

2.3 循環鏈表

 
         

1. 循環單鏈表

 
         

與單鏈表的區別在於,表中最后一個節點的指針不為null,而改為指向頭結點(第一個節點),從而整個鏈表形成一個環。判斷循環單鏈表是否為空,判斷是否等於頭指針。

 
         

只有一個尾指針的循環單例表,可以很方便的操作表頭和表尾,因為尾指針的后繼就是頭指針O(1) 。

 
         

 

 
         

 

 
         

2. 循環雙鏈表

 
         

與雙鏈表的區別在於,頭結點的prior指針指向尾節點,尾節點的next指針指向頭結點。

 
         

 

 
         

2.4 靜態鏈表

 
         

靜態鏈表是借助數組來描述線性表的鏈式存儲結構,節點也有數據域和指針域,這里的指針是節點的相對地址(數組下標),也需要預先分配一塊連續的內存空間。

 
         

特點,插入刪除和動態鏈表一樣,以next==-1為結束標志。

 
         

 

 
         

2.5 順序表和鏈表的比較

 
         

1. 順序表可以順序存取,也支持隨機存取;鏈表只能順序存取。

 
         

2. 順序表邏輯上相鄰的物理上也相鄰;而鏈表不一定,它是用指針來描述元素之間的關系。

 
         

3. 順序表插入和刪除要移動大量元素;鏈表只需修改指針即可


免責聲明!

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



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