目錄html
1、鏈表知識
1.1 鏈表定義
1.2 鏈表結構
1.3 優勢
1.4 單鏈表、雙鏈表、循環鏈表拓展
1.5 本文說明
2、面向對象分析鏈表
2.1 節點封裝類Node.java
2.2 鏈表封裝類ChainTable.java
2.3 關於環的補充
2.4 鏈表測試類TestChainTable.javajava
由指針連接n 個結點組成一個鏈表。它是線性表的鏈式存儲映像,稱爲線性表的鏈式存儲結構。node
結點:數據元素的存儲映像,映射。每一個節點由數據域和指針域兩部分組成。
數據域:存儲元素數據,即當前節點的存儲數據
指針域:存儲下一個節點的存儲位置,即指向下一個節點的指針數組
鏈表的元素是節點,由一個或多個結點組成。節點包括兩個元素:數據域(存儲數據的)和指針域(指向下一個結點地址)。數據結構
簡單理解的話,相似鏈條,一節一節相連,每一個鏈節都有本身的零件(數據)而且連接下一個連接(指針)。app
自行車的車鏈是一個環狀的鏈子,或者說是首位相連的,這是鏈表中環結構下面會有說明。函數
咱們能夠從圖1-1 鏈表中抽象出鏈表如圖1-2 所示,從首節點headNode 依此指向下一個node,直至尾節點tailNodeoop
圖1-二、抽象鏈表圖測試
進而具體到單向鏈表this
- 初始化指針指向首節點headNode,初始化指針的next 爲null 即鏈表爲空
- 每個節點node 都由數據域和指針域組成,數據域存放當前節點的數據,指針域存放當前指針的下一個指向節點
- 尾節點tailNode 的指針爲空
動態存儲形式,數據元素可自由擴充;
在物理存儲空間上並不必定相連,因此鏈表的插入、刪除動做高效,不須要像數組、順序表那樣移動過多的元素。
常見鏈表有單向鏈表和雙向鏈表,單向鏈表是隻有一個方向,從鏈表的首節點headNode 一直指向尾節點tailNode。雙向鏈表是鏈表便可從headNode 依此指向tailNode 又可反向從tailNode 依此指向heaNode。另外循環鏈表是鏈表的尾節點直接指向頭節點,即tailNode.next = headNode
單鏈表、雙鏈表、循環鏈表:
結點只有一個指針域的鏈表,稱爲單鏈表或線性鏈表
有兩個指針域的鏈表,稱爲雙鏈表
首尾相接的鏈表稱爲循環鏈表
本文涉及到鏈表的多個經常使用方法,包括鏈表的初始化、添加節點、刪除節點、查詢節點、鏈表的逆置、模擬鏈表的環結構、判斷鏈表是否存在環結構、尋找環的入口等方法。關於鏈表的相交問題暫不涉及。
此處以單向鏈表爲例,面向對象分析鏈表結構,將節點對象化,鏈表對象化,此處使用Java 語言演示。
有兩個屬性,當前節點存儲的數據Object data,指向下一節點的指針Node next。
鏈表是由一個或多個節點組成的。定義以下封裝類:
/** * 鏈表 * 由一個或多個節點組成 * 每個節點存放下一個元素, 經過首節點便可獲取鏈表所有節點元素, 所以能夠將首節點做爲鏈表對象 * 節點: * 每一個節點包含兩個元素: 數據對象data 和下一個節點對象next * 經過data 存儲當前節點的數據 * 經過next 存儲下一個節點 * * @Description :鏈表類 * @Author: niaonao * @Date: 2018/8/11 13:07 */ public class ChainTable { //聲明鏈表 private Node chain; /** * 構造函數 * 初始化鏈表, 此時chain.next == null, 即鏈表爲空 */ public ChainTable() { chain = new Node(); } //鏈表方法待補充 }
封裝單鏈表的經常使用方法包括插入首節點,插入尾節點,指定位置插入節點,刪除指定位置節點等。
方法不一一分開介紹了,其中的方法都有註釋說明。
基本方法:
- void insert(Object val) 插入鏈表元素的方法(插入鏈表首位, 插入鏈表尾部, 插入鏈表指定位置)
- int getLength() 獲取鏈表長度的方法
- Node getPosition(int position) 獲取鏈表指定位置元素(正序獲取, 逆序獲取)
- boolean judgeLoop() 判斷鏈表是否有環的方法
- int getLoopLength() 獲取環的長度
- Node entryLoop() 查找環入口的方法
- Node reverse() 逆置鏈表的方法
- void clear() 清除鏈表
TestChainTable.java
測試鏈表封裝類的經常使用方法,以供參考。
/** * @Description :鏈表測試類 * @Author: niaonao * @Date: 2018/8/11 14:11 */ public class TestChainTable { //聲明鏈表 private static ChainTable chainLink; public static void main(String a[]) { testChainMethod(); } /** * 測試鏈表方法 */ private static void testChainMethod() { System.out.println("\n1.1 初始化鏈表數據"); init(); if (chainLink == null || chainLink.getLength() < 1) { return; } showChain(); System.out.println("\n2.1 鏈表第三個節點插入數據爲Three 的節點"); chainLink.insert("Three", 3); showChain(); System.out.println("\n3.1 獲取鏈表中第5 個節點的數據: " + chainLink.getPosition(5).getData()); showChain(); System.out.println("\n4.1 獲取鏈表中倒數第5 個節點的數據: " + chainLink.getBackPosition(5).getData()); showChain(); System.out.println("\n5.1 鏈表刪除第2 個節點 "); chainLink.delete(2); showChain(); System.out.println("\n6.1 鏈表逆序"); chainLink.reverse(); showChain(); System.out.println("\n7.1 鏈表是否相交: " + chainLink.judgeLoop()); showChain(); System.out.println("\n7.2 模擬環模型, 使當前鏈表尾節點的Next 指向首節點"); Node firstNode = chainLink.getPosition(1); Node lastNode = chainLink.getBackPosition(1); lastNode.setNext(firstNode); //出現環時, 鏈表遍歷是個死循環 //showChain(); if (chainLink.judgeLoop()){ System.out.print("\n7.3 鏈表是否有環: " + Boolean.TRUE + "\n\t出現環時, 鏈表遍歷是個死循環"); System.out.print("\n\t環的長度: " + chainLink.getLoopLength()); System.out.print("\n\t環的入口: " + chainLink.entryLoop() + "\n\t\t環入口節點的數據data: " + chainLink.entryLoop().getData() + "\n\t\t下一個節點對象node: " + chainLink.entryLoop().getNext()); } else { System.out.println("\n7.3 鏈表是否有環: " + Boolean.TRUE + "\n\t" + chainLink); } } /** * 初始化數據 */ private static void init() { chainLink = new ChainTable(); System.out.println("\t在鏈表首位添加A,鏈表尾部依此添加B、C、D、E"); chainLink.insertHead("A"); chainLink.insertTail("B"); chainLink.insertTail("C"); chainLink.insertTail("D"); chainLink.insertTail("E"); } /** * 鏈表數據顯示 */ private static void showChain() { System.out.println("\t鏈表長度: " + chainLink.getLength()); System.out.print("\t鏈表數據: "); for (int i = 0; i < chainLink.getLength(); i++) { Node node = chainLink.getPosition(i + 1); System.out.print("\t " + node.getData()); } } }
測試結果:
1.1 初始化鏈表數據
在鏈表首位添加A,鏈表尾部依此添加B、C、D、E
鏈表長度: 5
鏈表數據: A B C D E
2.1 鏈表第三個節點插入數據爲Three 的節點
鏈表長度: 6
鏈表數據: A B Three C D E
3.1 獲取鏈表中第5 個節點的數據: D
鏈表長度: 6
鏈表數據: A B Three C D E
4.1 獲取鏈表中倒數第5 個節點的數據: B
鏈表長度: 6
鏈表數據: A B Three C D E
5.1 鏈表刪除第2 個節點
鏈表長度: 5
鏈表數據: A Three C D E
6.1 鏈表逆序
鏈表長度: 5
鏈表數據: E D C Three A
7.1 鏈表是否相交: false
鏈表長度: 5
鏈表數據: E D C Three A
7.2 模擬環模型, 使當前鏈表尾節點的Next 指向首節點
7.3 鏈表是否有環: true
出現環時, 鏈表遍歷是個死循環
環的長度: 5
環的入口: Node@2503dbd3
環入口節點的數據data: E
下一個節點對象node: Node@4b67cf4d