Java學習筆記--鏈表


心在山東身在吳,飄蓬江海漫嗟吁。

他時若遂凌雲志, 敢笑黃巢不丈夫。

               ——水滸傳

先上源代碼,LinkedList類:

 1 private static class Node<E> {
 2         E item;
 3         Node<E> next;
 4         Node<E> prev;
 5 
 6         Node(Node<E> prev, E element, Node<E> next) {
 7             this.item = element;
 8             this.next = next;
 9             this.prev = prev;
10         }
11     }

Java鏈表中定義了一個內部類Node類,"node"是節點的意思.鏈表的基本元素是節點,(雙向鏈表)每個節點包含三個成員,分別是item:數據,next:指向鏈表下一個元素的指針,prev:指向上一個元素的指針

先看一下C中的鏈表:

頭指針變量保存了一個地址,它指向一個變量No.1,No.1中又保存了一個指針,它指向No.2,以此類推,直到No.X中保存的地址指向No.last,圖中最后一項為No.3,它指向NULL。

雙向鏈表每個元素中又加入了prev指針。

雙向鏈表圖:

但是java中沒有指向內存地址的指針,那么如何實現鏈表呢?

再看Java源代碼:

 1  transient int size = 0;
 2 
 3     /**
 4      * Pointer to first node.
 5      * Invariant: (first == null && last == null) ||
 6      *            (first.prev == null && first.item != null)
 7      */
 8     transient Node<E> first;
 9 
10     /**
11      * Pointer to last node.
12      * Invariant: (first == null && last == null) ||
13      *            (last.next == null && last.item != null)
14      */
15     transient Node<E> last;
16 
17     /**
18      * Constructs an empty list.
19      */
20     public LinkedList() {
21     }
22 
23     /**
24      * Constructs a list containing the elements of the specified
25      * collection, in the order they are returned by the collection's
26      * iterator.
27      *
28      * @param  c the collection whose elements are to be placed into this list
29      * @throws NullPointerException if the specified collection is null
30      */
31     public LinkedList(Collection<? extends E> c) {
32         this();
33         addAll(c);
34     }
View Code

LinkedList類定義了兩個臨時節點first和last,兩個構造器.一個無參構造和一個帶參構造,無參構造創建鏈表實例,帶參構造可以把一個集合整體加入鏈表

下面看一下add()方法:

1 public boolean add(E e) {
2         linkLast(e);
3         return true;
4     }
 1 void linkLast(E e) {
 2         final Node<E> l = last;
 3         final Node<E> newNode = new Node<>(l, e, null);
 4         last = newNode;
 5         if (l == null)
 6             first = newNode;
 7         else
 8             l.next = newNode;
 9         size++;
10         modCount++;
11     }

畫圖:

初始鏈表為空的情況:prev和next都是null,item是e,這里假設傳入的數據是No.1,No.2...;

此時再加入元素:

加入第三個元素:

加入第四個元素:

以此類推。。。

可見java中鏈表是用引用變量指向節點來代替C中的指針變量指向內存地址。

每次加入新的元素,只需要將原last元素的next指向新加入元素的實例,把新加入元素的prev指向原last元素的實例。

再看下add(int index, E element)方法:

1 public void add(int index, E element) {
2         checkPositionIndex(index);
3 
4         if (index == size)
5             linkLast(element);
6         else
7             linkBefore(element, node(index));
8     }
 1 Node<E> node(int index) {
 2         // assert isElementIndex(index);
 3 
 4         if (index < (size >> 1)) {
 5             Node<E> x = first;
 6             for (int i = 0; i < index; i++)
 7                 x = x.next;
 8             return x;
 9         } else {
10             Node<E> x = last;
11             for (int i = size - 1; i > index; i--)
12                 x = x.prev;
13             return x;
14         }
15     }

這里假定傳入的index比size小,

node(int index)用很簡單的方式返回了位置為index的Node實例,然后執行linkBefore(E e, Node<E> succ)方法

 1 void linkBefore(E e, Node<E> succ) {
 2         // assert succ != null;
 3         final Node<E> pred = succ.prev;
 4         final Node<E> newNode = new Node<>(pred, e, succ);
 5         succ.prev = newNode;
 6         if (pred == null)
 7             first = newNode;
 8         else
 9             pred.next = newNode;
10         size++;
11         modCount++;
12     }

把newNode 的prev 指向原位置節點的prev節點,next 指向原位置節點;

把原位置節點的prev指向newNode;

最后把原位置節點的prev節點(如果有)的next指向newNode;如果沒有,則newNode為第一個節點,原位置節點變為第二個節點;

此處省略其他鏈表方法...原理是一樣的.

 


免責聲明!

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



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