1. 程式人生 > >Java學習筆記之連結串列

Java學習筆記之連結串列

連結串列是一種非常常見和重要的資料結構,在java裡也可以通過引用傳遞的方式進行實現。

1、基本概念

什麼是連結串列,通俗的可以理解為一輛貨車,火車頭代表連結串列表頭,後面的每一節車廂表示一個連結串列的結點,每一個結點除了儲存本節點的資料以外,還得帶上下一個結點的引用,也就是除了車尾以外的那些車廂,都必須連線後面的一節車廂。

在這裡插入圖片描述

2、連結串列的實現

要實現連結串列,我們必須定義一個連結串列類,在類中還得有一個屬性,可以儲存下一個節點的引用地址。

每一個節點除了要儲存當前節點的資料,還得帶上下一個結點的引用地址。

class Node{
    private
String data; // 節點的資料 private Node next; // 下一個節點的引用地址 public Node(String data){ // 建構函式設定節點內容 this.data = data; } public Node getNext() { return this.next; // 獲取下一個節點 } public void setNext(Node next) { this.next = next; // 設定下一個節點 } public
String getData(){ return this.data; } } public class LinkDemo { public static void main(String[] args) { Node root = new Node("火車頭"); Node node1 = new Node("一號車廂"); Node node2 = new Node("二號車廂"); Node node3 = new Node("三號車廂"); root.setNext(node1)
; node1.setNext(node2); node2.setNext(node3); printNode(root); // 從頭開始輸出 } public static void printNode(Node node) { System.out.print(node.getData()+" -> "); if(node.getNext()!=null){ printNode(node.getNext()); // 遞迴呼叫節點 } } }

上述例子中,所有的關係都是使用者手動設定,如果想讓它真正有意義,我們需要加入一個操作的封裝。

2、連結串列的改進

可以看到,上面的實現的連結串列需要人工手動去操作節點,一個個新增,一個個處理引用關係,非常繁瑣,因此我們應該將對節點的操作進行封裝。常見的操作有:增加資料、查詢資料、刪除資料。
注意:刪除資料其實只是改變節點引用地址而已

在這裡插入圖片描述

  • 增加節點:在連結串列最後追加
  • 查詢節點:遞迴查詢
  • 刪除節點:修改引用關係
2.1 新增節點
class Link{ // 連結串列的完成類
    class Node{ // 節點類
        private String data;
        private Node next;
        public Node(String data){
            this.data = data;
        }

        public void add(Node newNode){ // 將節點加入到合適的位置
            if(this.next==null){  // 如果下一個節點為空,則把新節點設定在next位置
                this.next = newNode;
            }else{   // 如果下一節點非空,則繼續向後遞迴查詢
                this.next.add(newNode);
            }
        }

        public void print(){
            System.out.print(this.data + " -> ");  // 輸出節點內容
            if(this.next!=null){        // 判斷是否為最後一個節點,若不是則繼續遞迴呼叫
                this.next.print();
            }
        }
    }

    private Node root;   // 設定根節點
    public void addNode(String data){   // 增加節點
        Node newNode = new Node(data);  // 定義新的節點
        if(this.root==null){    // 如果根節點為空,則設定 newNode 為根節點
            this.root = newNode;
        }else{                  // 如果不是根節點,利用add方法把節點放在合適的位置
            this.root.add(newNode);
        }

    }

    public void printNode(){    // 輸出連結串列內容
        if(this.root!=null){    // 如果連結串列根元素不為空
            this.root.print();  // 呼叫Node類中的輸出操作
        }
    }


}

public class LinkDemo2 {
    public static void main(String[] args) {
        Link link = new Link();
        link.addNode("A");	  // 增加節點
        link.addNode("B");
        link.addNode("C");
        link.addNode("D");
        System.out.println("------------------");
        link.printNode();
    }
}
2.2 查詢節點
class Link{ // 連結串列的完成類
    class Node{ // 節點類
        private String data;
        private Node next;
        public Node(String data){
            this.data = data;
        }

        public void add(Node newNode){ // 將節點加入到合適的位置
            if(this.next==null){  // 如果下一個節點為空,則把新節點設定在next位置
                this.next = newNode;
            }else{   // 如果下一節點非空,則繼續向後遞迴查詢
                this.next.add(newNode);
            }
        }

        public void print(){
            System.out.print(this.data + " -> ");  // 輸出節點內容
            if(this.next!=null){        // 判斷是否為最後一個節點,若不是則繼續遞迴呼叫
                this.next.print();
            }
        }

        public boolean search(String data){  // 內部搜尋方法
            if(data.equals(this.data)){      // 判斷當前節點資料和查詢資料是否一致
                return true;
            }else{      // 繼續向後判斷
                if(this.next!=null){         // 如果下一個節點存在,繼續判斷是否資料相等
                    return this.next.search(data);
                }else{                       // 否則返回失敗
                    return false;
                }
            }
        }


    }

    private Node root;   // 設定根節點
    public void addNode(String data){   // 增加節點
        Node newNode = new Node(data);  // 定義新的節點
        if(this.root==null){    // 如果根節點為空,則設定 newNode 為根節點
            this.root = newNode;
        }else{                  // 如果不是根節點,利用add方法把節點放在合適的位置
            this.root.add(newNode);
        }

    }

    public void printNode(){    // 輸出連結串列內容
        if(this.root!=null){    // 如果連結串列根元素不為空
            this.root.print();  // 呼叫Node類中的輸出操作
        }
    }

    public boolean contains(String name){   // 判斷元素是否存在
        return this.root.search(name);
    }


}

public class LinkDemo2 {
    public static void main(String[] args) {
        Link link = new Link();
        link.addNode("A");
        link.addNode("B");
        link.addNode("C");
        link.addNode("D");
        System.out.println("------------------");
//        link.printNode();
        System.out.println(link.contains("X"));
    }
}
2.3 刪除節點
class Link{ // 連結串列的完成類
    class Node{ // 節點類
        private String data;
        private Node next;
        public Node(String data){
            this.data = data;
        }

        public void add(Node newNode){ // 將節點加入到合適的位置
            if(this.next==null){  // 如果下一個節點為空,則把新節點設定在next位置
                this.next = newNode;
            }else{   // 如果下一節點非空,則繼續向後遞迴查詢
                this.next.add(newNode);
            }
        }

        public void print(){
            System.out.print(this.data + " -> ");  // 輸出節點內容
            if(this.next!=null){        // 判斷是否為最後一個節點,若不是則繼續遞迴呼叫
                this.next.print();
            }
        }

        public boolean search(String data){  // 內部搜尋方法
            if(data.equals(this.data)){      // 判斷當前節點資料和查詢資料是否一致
                return true;
            }else{      // 繼續向後判斷
                if(this.next!=null){         // 如果下一個節點存在,繼續判斷是否資料相等
                    return this.next.search(data);
                }else{                       // 否則返回失敗
                    return false;
                }
            }
        }

        public void delete(Node previous, String data){
            if(data.equals(this.data)){     // 找到匹配的節點
                previous.next = this.next;  // 空出當前節點
            }else{
                if(this.next!=null){        // 還是存在下一個節點
                    this.next.delete(this, data);
                }
            }
        }


    }

    private Node root;   // 設定根節點
    public void addNode(String data){   // 增加節點
        Node newNode = new Node(data);  // 定義新的節點
        if(this.root==null){    // 如果根節點為空,則設定 newNode 為根節點
            this.root = newNode;
        }else{                  // 如果不是根節點,利用add方法把節點放在合適的位置
            this.root.add(newNode);
        }

    }

    public void printNode(){    // 輸出連結串列內容
        if(this.root!=null){    // 如果連結串列根元素不為空
            this.root.print();  // 呼叫Node類中的輸出操作
        }
    }

    public boolean contains(String name){   // 判斷元素是否存在
        return this.root.search(name);
    }

    public void deleteNode(String data){
        if(this.contains(data)){  // 判斷節點是否存在
            // 一定要判斷此元素是否和根節點相等
            if(this.root.data.equals(data)){    // 內容是根節點
                this.root = this.root.next;     // 修改根節點,把第一個節點設定為根節點
            }else{
                this.root.next.delete(root, data);      // 把下一個節點的前節點和資料傳入繼續判斷
            }

        }
    }


}

public class LinkDemo2 {
    public static void main(String[] args) {
        Link link = new Link();
        link.addNode("A");
        link.addNode("B");
        link.addNode("C");
        link.addNode("D");
        System.out.println("--------- 刪除之前 ---------");
        link.printNode();
//        System.out.println(link.contains("X"));
        link.deleteNode("C");
        link.deleteNode("B");
        link.deleteNode("A");
        System.out.println();
        System.out.println("--------- 刪除之後 ---------");
        link.printNode();
        System.out.println();
        System.out.println("查詢節點D: " + link.contains("D"));
    }
}