Java無頭單向非循環鏈表實現(實現及測試都有示例代碼)

一,鏈表的概念及結構

  • 概念:

鏈表是一種物理存儲結構上非連續存儲結構,數據元素的邏輯順序是經過鏈表中的引用連接次序實現的。html

  • 結構:
    實際中鏈表的結構很是多樣,如下狀況組合起來就有八種鏈表結構;node

    • 單向 , 雙向
    • 帶頭 , 不帶頭
    • 循環 , 非循環

二,代碼實現

下面只介紹無頭單向非循環鏈表的實現測試

  • 代碼實現:
// 一個節點
class Node {
    public int data;   // 數據
    public Node next = null;  // 下一個節點的位置
    public Node(int data) {
        this.data = data;
    }
}
public class LinkedList {
    // 管理全部的鏈表節點. 只須要記錄頭結點的位置便可
    // 初始狀況下 head 爲 null, 此時表示空鏈表(不帶傀儡節點)
    private Node head = null;
    // private Node tail = null; // 優化尾插
    // private int size = 0; // 優化獲取長度
    public void addFirst(int data) {
        // 1. 根據 data 值構建一個鏈表節點(Node對象)
        Node node = new Node(data);
        // 2. 若是鏈表爲空鏈表
        if (head == null) {
            head = node;
            return;
        } 
語言 方法
3013 Hsg7R912UO
tRLDU 抖音文案
4267 2012-08-16 04:24:30
// 3. 若是鏈表不是空鏈表
        node.next = head;
        head = node;
    }
    public void addLast(int data) {
        // 1. 根據 data 構造一個 Node 對象
        Node node = new Node(data);
        // 2. 若是鏈表爲空鏈表
        if (head == null) {
            head = node;
            return;
        }
        // 3. 若是鏈表非空, 須要先找到這個鏈表末尾的最後一個節點
        Node tail = head;
        while (tail.next != null) {
            tail = tail.next;
        }
        // 循環結束以後, tail 就對應到最後一個節點了
        tail.next = node;
    }
    public void display() {
        // 把鏈表中的每一個元素都打印出來
        for (Node cur = head; cur != null; cur = cur.next) {
            System.out.print(cur.data + " ");
        }
        System.out.println();
    }
    public int getSize() {
        int size = 0;
        for (Node cur = head; cur != null; cur = cur.next) {
            size++;
        }
        return size;
    }
    // 插入成功, 返回 true, 不然 false
    public boolean addIndex(int index, int data) {
        int size = getSize();
        // 1. 斷定 index 是否有效
        if (index < 0 || index > size) {
            // index 無效, 插入失敗
            return false;
        }
        // 2. 若是 index 爲 0, 至關於頭插
        if (index == 0) {
            addFirst(data);
            return true;
        }
        // 3. 若是 index 爲 size, 至關於尾插
        if (index == size) {
            addLast(data);
            return true;
        }
        Node node = new Node(data);
        // 4. 若是 index 是一箇中間的位置
        // a) 先找到 index 的前一個節點 index - 1
        Node prev = getPos(index - 1);
        // b) 接下來就把新節點插入到 prev 以後
        // 註釋是頭插的代碼
        // node.next = head;
        // head = node;
        node.next = prev.next;
        prev.next = node;
        return true;
    }
  • 代碼測試

 
// 給定 index 下標, 找到對應的節點
    private Node getPos(int index) {
        Node cur = head;
        for (int i = 0; i < index; i++) {
            // cur.next 操做以前必需要保證
            // cur 是非 null 的
            cur = cur.next;
        }
        return cur;
    }
    public boolean contains(int toFind) {
        for (Node cur = head; cur != null; cur = cur.next) {
            if (cur.data == toFind) {
                return true;
            }
        }
        return false;
    }
    public void remove(int toRemove) {
        // 1. 若是要刪除元素是頭結點, 特殊處理一下
        if (head.data == toRemove) {
            // 頭結點要被刪掉
            head = head.next;
            return;
        }
        // 2. 若是要刪除元素不是頭結點, 找到要刪除節點的前一個位置
        Node prev = searchPrev(toRemove);
        // 3. 修改引用的指向, 完成刪除
        // prev.next = prev.next.next;
        Node toDelete = prev.next;
        prev.next = toDelete.next;
    }
    private Node searchPrev(int toRemove) {
        // 找到 toRemove 的前一個節點
        for (Node cur = head; cur != null
                && cur.next != null; cur = cur.next) {
            if (cur.next.data == toRemove) {
                return cur;
            }
        }
        return null;
    }
    public void removeAll(int toRemove) {
        // 1. 先刪除非頭結點, 須要找到待刪除節點的前一個位置
        // prev 始終指向 cur 的前一個位置
        Node prev = head;
        Node cur = head.next;
        while (cur != null) {
            if (cur.data == toRemove) {
                // cur 節點須要被刪除掉
                prev.next = cur.next;
                cur = prev.next;
            } else {
                // prev 和 cur 同步日後移動
                prev = cur;
                cur = cur.next;
            }
        }
        // 2. 處理頭結點爲要刪除節點的狀況
        if (head.data == toRemove) {
            head = head.next;
        }
    }
    public void clear() {
        head = null;
    }
}
  • 測試代碼
public class Test{
 private static void testAddFirst(){   //測試頭插
    LinkedList6 List = new LinkedList6(); 
    List.addFirst(1);
    List.addFirst(1);
    List.addFirst(1);
    List.addFirst(1);
    List.display();   //測試鏈表打印
   int size =  List.getSize(); //測試獲取鏈表長度
   System.out.println(size);
 }  
 private static void testAddLast(){  //測試尾插
       LinkedList6 List1 = new LinkedList6(); 
       List1.addLast(1);
       List1.addLast(2);
       List1.addLast(3);
       List1.addLast(4);
       List1.addLast(5);
       List1.display();
       List1.addIndex(2,8);  //測試指定位置插入
       List1.display();
       boolean result = List1.contains(10); //測試鏈表是否包含某個元素
       System.out.println(result);
       List1.remove(8); //測試刪除鏈表中指定節點(從左到右第一個出現的)
       List1.display();
       List1.addLast(1);
       List1.addLast(1);
       List1.addLast(1);
        List1.display();
        List1.removeAll(1); //測試刪除鏈表中指定元素的全部節點
        List1.display();
        List1.clear();  //測試清空鏈表
        List1.display();
 }
 public static void main(String[] args){
     //testAddFirst();
     testAddLast();
 }
}
相關文章
相關標籤/搜索