1.特點
通過指針連接起來的結點存儲數據元素;
2. 節點結構由數據域和指針域組成
3.分類
3.1 單鏈表
說明,頭部指向第一個元素的地址,第一個元素指針域指向第二個元素,依次指向,最後一個元素指針域爲空,沒有指向其它元素,這樣的節點通過指針域構成起來的鏈表稱爲單鏈表
3.2 循環鏈表
最後一個元素的指針域指向頭部構成一個元素鏈表
3.3 雙鏈表
有兩個指針域,記住前一個元素的地址和後一個元素的地址,可以從雙向遍歷元素,相比於單鏈表遍歷方式增加靈活性,但是佔用多一個指針域空間
4.單鏈表插入和刪除示意圖
4.1 在單鏈表中插入結點
插入新元素c,把a元素的指針域指向c元素,把c元素的指針指向b元素
4.2 單鏈表中刪除元素
刪除b元素,a元素指向b元素的指針改成指向c元素
5.Java語言實現鏈式
5.1 說明:定義一個靜態內部類Node,稱爲結點,結點與結點相連在一起構成鏈式數據結構,每個結點有兩個數據域,一個指向數據,另一個指向另外一個結點
5.2 在包中定義一個靜態內部類
/** * 定義一個嵌套類,嵌套類與內部類的區別在於嵌套類是靜態,內部類不是靜態 * @param <E> */ private static class Node<E> { /** * 指向對象一個引用,結點的數據部分 */ E data; /** * 指向下一個結點引用 */ Node next; public Node(E data, Node next) { this.data = data; this.next = next; } }
5.3 外部類添加方法
/** * 添加元素方法 * @param e * @return */ public boolean add(E e){ //創建一個新結點,數據域保持數據對象 Node<E> newNode = new Node<>(e); //記下前面一個結點地址 newNode.next = first; //把當前結點賦給頭結點 first = newNode; size ++; return true; }
測試效果如下:
封裝的數據格式如下:
6.簡單代碼示意
public class CustomLinkedList<E> { /** * 頭引用,指向第一個元素 */ private Node first; /** * 記錄元素的個數 */ private int size; /** * 添加元素方法 * @param e * @return */ public boolean add(E e){ //創建一個新結點,數據域保持數據對象 Node<E> newNode = new Node<>(e); //記下前面一個結點地址 newNode.next = first; //把當前結點賦給頭結點 first = newNode; size ++; return true; } public Object[] toArray(){ Object[] result = new Object[size]; int i = 0; for(Node<E> e = first;e != null; e = e.next){ result[i++] = e.data; } return result; } /** * 判斷結點鏈中數據域是否等於給定的值 * @param e * @return */ public boolean contains(E e){ if(e == null){ return false; } boolean found = false; Node<E> currentNode = first; while(!found && currentNode != null){ if(e.equals(currentNode.data)){ found = true; }else { currentNode = currentNode.next; } } return found; } /** * 基本思路是刪除一個結點,並將頭引入指向第二結點 * @return */ public E remove(){ E result = null; if(first != null){ //讀取頭結點數據域 result = (E)first.data; //將頭結點指向第二個結點 first = first.next; size --; } return result; } /** * 1.用鏈中的第一個結點數據域替換要移除值所在的結點 * 2.從鏈中刪除第一個結點 * @param e * @return */ public boolean remove(E e){ boolean result = false; Node<E> currentElementNode = getReferenceNode(e); if( currentElementNode != null){ //當前結點數據域保持第一個結點數據域 currentElementNode.data = (E)first.data; //移除第一個結點 first = first.next; size --; result = true; } return result; } /** * 清空鏈表 */ public void clear(){ while (!isEmpty()){ remove(); } } /** * 判斷是否爲空 * @return */ public boolean isEmpty(){ return size == 0; } /** * 根據給定的元素,獲取該元素在鏈中的結點引用 * @param e * @return */ private Node<E> getReferenceNode(E e){ boolean found = false; Node<E> currentNode = first; while (!found && currentNode != null){ if(e.equals(currentNode.data)){ found = true; }else { currentNode = currentNode.next; } } return currentNode; } /** * 定義一個嵌套類,嵌套類與內部類的區別在於嵌套類是靜態,內部類不是靜態 * @param <E> */ private static class Node<E> { /** * 指向對象一個引用,結點的數據部分 */ E data; /** * 指向下一個結點引用 */ Node next; public Node(E data) { this.data = data; } public Node(E data, Node next) { this.data = data; this.next = next; } } }