學習JAVA—數據結構之單鏈表與數組的區別、以及實現zt


學習JAVA—數據結構之單鏈表與數組的區別、以及實現

http://blog.csdn.net/gg811/article/details/8466614 這是大牛地址

 

          第一部分是首先說下數組與鏈表的區別~數組是大家常用的而熟知的,利用鏈表對比數組這樣可以加深對鏈表的記憶。第二部分就是鏈表的代碼實現,加深理解。

關於單鏈表:

1、概念

                在單鏈表中由於數據元素的存儲空間一般不是連續的,因此為了完善的表示單鏈表的邏輯結構,其中每一個數據元素必須由兩部分構成:一部分是數據元素中的數據值,另一部分是數據元素的地址值。這兩部分信息構成了單鏈表的一個節點。因此,在用單鏈表表示線性表時,每個結點的存儲地址是任意的,即存儲位置是無序的。

2、結構

                對於單鏈表來說,每個節點的結構都是(data,next),節點中有兩個部分:data域—存放結點值的數據域,next—存放結點的直接后續的地址的鏈域。

 

數組與鏈表的區別:

1、基於空間的考慮

            數組的存儲空間是靜態,連續分布的,初始化的過大造成空間浪費,過小又將使空間溢出機會增多。而鏈表的存儲空間是動態分布的,只要內存空間尚有空閑,就不會產生溢出;鏈表中每個節點出了數據域外,還有鏈域(指向下一個節點),這樣空間利用率就會變高。

2、基於時間的考慮

            具體的來說 數組查詢快,插入與刪除慢,單鏈表查詢慢,插入與刪除快。細說的話:數組中任意節點都可以在O(1)內直接存儲訪問,而鏈表中的節點,需從頭指針順着鏈表掃描才能獲取到;而鏈表任意位置進行插入和刪除,都只需要修改指針,而數組中插入刪除節點,平均要移動一半的節點。

 

           (靜態)數組從棧中分配空間,對於程序員方便快速,但是自由度小。鏈表從堆中分配空間,自由度大但是申請管理比較麻煩。

              數組中的數據在內存中按順序存儲的,而鏈表是隨機存儲的!

              要訪問數組中的元素可以按下標索引來訪問,速度快,如果對他進行插入操作的話,就得移動很多元素,所以對數組進行插入操作效率很低!

              由於鏈表是隨機存儲的,鏈表在插入,刪除操作上有很高的效率(相對於數組),如果要訪問鏈表中的某個元素的話,就得從鏈表的頭逐個遍歷,直到找到所需要的元素為止,所以鏈表的隨機訪問的效率就比數組要低。(這里會在下面代碼中顯示出來,在此做一個特殊的符號標記一下生氣,嗯就是這個把)。

 

單鏈表的實現代碼,走你~:

首先定義一個節點類~記錄每個節點使用:

[java]  view plain copy
 
  1. public class Node {  
  2.   
  3.     String data;//數據域  
  4.     Node next;//鏈域  
  5.   
  6.     public Node(String data) {  
  7.         this.data = data;  
  8.         next = null;  
  9.     }  
  10.   
  11. }  

 

下列代碼就是構造了一個單鏈表,並且實現了各種操作:

 

[java]  view plain copy
 
  1. public class LinkedList {  
  2.   
  3.     int lenght;// 鏈表的長度  
  4.     Node head;// 定義頭結點  
  5.   
  6.     public LinkedList() {  
  7.         head = null;// 鏈表中的頭結點  
  8.         lenght = 0;  
  9.     }  
  10.   
  11.     /** 在鏈表末尾添加一個元素 */  
  12.     public void addElement(Node n) {  
  13.         if (lenght == 0) {// 如果鏈表為空,則直接添加。  
  14.             head = n;  
  15.         } else {  
  16.             Node t = head;  
  17.             while (t.next != null) {// 沿鏈表第一個元素向后尋找,直到找到末尾  
  18.                 t = t.next;  
  19.             }  
  20.             t.next = n;// 在末尾添加元素,也就是給最后一個next賦值~讓鏈域不為空,這樣鏈域為空的就成了鏈表中最后一個元素  
  21.         }  
  22.         // 在主函數中調用這個的方法為addElement(new Node("張三")),  
  23.         // 其中new一個Node 就確定了這個Node的數據域(data)為"張三",鏈域(next)為null,  
  24.         // 而這個函數的作用就是確定把這個新new出來Node放在誰的next中  
  25.         lenght++;// 修改長度  
  26.     }  
  27.   
  28.     /** 在鏈表中特定位置添加一個元素 */  
  29.     public boolean insert(Node n, int index) {  
  30.         if (index > lenght && index < 0) {// 如果插入位置超出鏈表長度  
  31.             System.out.println("超出范圍!!");  
  32.             return false;  
  33.         } else {  
  34.             Node t = head;  
  35.             if (index == 0) {  
  36.                 n.next = head;// 讓傳入的節點指向頭節點  
  37.                 head = n;// n作為新的頭節點  
  38.             } else {  
  39.                 for (int i = 0; i < index - 1; i++) {// 找到要插入的位置的前一個位置  
  40.                     t = t.next;  
  41.                 }  
  42.                 n.next = t.next;// 新插入的節點指向當前位置節點  
  43.                 t.next = n;  
  44.                 // 這里需要用圖解釋的更為清晰  
  45.                 // 可見本文下方圖—1;  
  46.             }  
  47.             lenght++;  
  48.             return true;  
  49.         }  
  50.     }  
  51.   
  52.     /** 刪除鏈表最后一個節點 */  
  53.     public void removeLastElement() {  
  54.         if (lenght == 0) {  
  55.             System.out.println("鏈表中沒有元素");  
  56.             return;  
  57.         }  
  58.         Node t = head;  
  59.         if (lenght == 1) {  
  60.             head = null;  
  61.         } else {  
  62.             for (int i = 0; i < lenght - 1; i++) {// 找到末尾節點的前一個節點  
  63.                 t = t.next;  
  64.             }  
  65.             t.next = null;  
  66.         }  
  67.         lenght--;  
  68.     }  
  69.   
  70.     /** 刪除指定位置的節點 */  
  71.     public void removeElement(int index) {  
  72.         if (lenght == 0) {  
  73.             System.out.println("鏈表沒有元素!");  
  74.             return;  
  75.         }  
  76.         if (index > lenght && index < 0) {  
  77.             System.out.println("超出范圍!!");  
  78.             return;  
  79.         }  
  80.         Node t = head;  
  81.         if (index == 0) {  
  82.             head = head.next;  
  83.             t.next = null;  
  84.             lenght--;  
  85.             return;  
  86.         }  
  87.   
  88.         for (int i = 0; i < index - 1; i++) {// 找到要刪除位置的前一位置  
  89.             t = t.next;  
  90.         }  
  91.         Node temp = t;  
  92.         t.next = t.next.next;  
  93.         temp.next = null;// 讓該節點的next指向空  
  94.         lenght--;  
  95.   
  96.     }  
  97.   
  98.     /** 清空鏈表 */  
  99.     public void clearList() {  
  100.         head = null;  
  101.         lenght = 0;  
  102.     }  
  103.   
  104.     /** 打印鏈表中的所有元素 */  
  105.     public void printList() {  
  106.         if (lenght == 0) {  
  107.             System.out.println("鏈表為空!");  
  108.             return;  
  109.         }  
  110.         Node t = head;  
  111.         while (t!= null) {  
  112.             System.out.print(t.data + " ");  
  113.             t = t.next;  
  114.         }  
  115.     }  
  116. }  

 

                                

                                                                                        圖—1

 

再接下來就是調用這個鏈表的各個操作了~順便瞎說說~在我沒學鏈表前~我看過嚴蔚敏老師的數據結構一書~其中的好多偽代碼我都曾嘗試用數組來解決,但是發現並沒有想象中那么容易實現~在學鏈表之后~再回顧數據結構這本書~其中大多數偽代碼都可以用鏈表來實現~我就覺得這個是我研究算法的一個好工具~嗯~廢話就這么多,以上這個栗子要是懶得動手打的話~我這還是會有一個打好的,同樣下載不要分數哦~~(http://download.csdn.net/detail/gg811/4963474)點擊打開鏈接


免責聲明!

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



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