1. 程式人生 > 實用技巧 >Java連結串列基礎

Java連結串列基礎

這次來學習下單鏈表的一些常見操作,連結串列是一種物理儲存結構上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。

建立連結串列

public class test {
    public static void main(String[] args) {
         int[] arr = {5,2,7,4,9,3,1};
         SingleLinkedList singleLinkedList = new SingleLinkedList();
         for(int i=0;i<arr.length;i++){
             singleLinkedList.add(arr[i]);
         }
         singleLinkedList.deleteNode(
1); singleLinkedList.printLink(); System.out.println(); //int len = singleLinkedList.length(); //System.out.println(len); } } class SingleLinkedList{ public Node head = new Node(); //head為頭節點不存放任何的資料,只是充當一個指向連結串列中真正存放資料的第一個節點的作用 class Node{ public
int value; public Node next; public Node() {} public Node(int value) { this.value = value; this.next = null; } } public void add(int value) {//增加節點 尾插法 if(head.next == null) { head.next = new Node(value);
return; } Node tempNode = head; while(tempNode.next!=null) { tempNode = tempNode.next; } tempNode.next = new Node(value); } public void printLink() {//遍歷連結串列 Node tempNode = head; while(tempNode.next!=null) { tempNode = tempNode.next; System.out.print(tempNode.value+" "); } } public void deleteNode(int value) {//根據值刪除節點 Node tempNode = head; while(tempNode.next!=null) { if(tempNode.next.value == value) { tempNode.next = tempNode.next.next; }else { tempNode = tempNode.next; } } } public int length(){ int length = 0; Node temp = head; while (temp.next!=null){ length++; temp = temp.next; } return length; } }

執行結果如下:

翻轉連結串列

public class test {
    public static void main(String[] args) {
         int[] arr = {5,2,7,4,9,3,1};
         SingleLinkedList singleLinkedList = new SingleLinkedList();
         for(int i=0;i<arr.length;i++){
             singleLinkedList.add(arr[i]);
         }
         singleLinkedList.reverseList();
         singleLinkedList.printLink();
    }
}

class SingleLinkedList{
    public Node head = new Node();  //head為頭節點不存放任何的資料,只是充當一個指向連結串列中真正存放資料的第一個節點的作用
    
    class Node{
        public int value;
        public Node next;
        public Node() {
            this.next = null;
        }
        public Node(int value) {
            this.value = value;
            this.next = null;
        }
    }
    
    public void add(int value) {//增加節點 尾插法
        if(head.next == null) {
            head.next = new Node(value);
            return;
        }
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
        }
        tempNode.next = new Node(value);
    }
    
    public void printLink() {//遍歷連結串列
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
            System.out.print(tempNode.value+" ");
        }
    }
    
    public void reverseList() {
        Node preNode = null;
        Node curNode = head;
        while(curNode!=null) {
            Node tempNode = curNode.next;
            curNode.next = preNode;
            preNode = curNode;
            curNode = tempNode;
        }
        Node newHeadNode = new Node();
        newHeadNode.next = preNode;
        head = newHeadNode;
    }
    
}

中間元素

public class test {
    public static void main(String[] args) {
         int[] arr = {5,2,7,4,9,3,1};
         SingleLinkedList singleLinkedList = new SingleLinkedList();
         for(int i=0;i<arr.length;i++){
             singleLinkedList.add(arr[i]);
         }
         int midvalue = singleLinkedList.findMiddle();
         System.out.println(midvalue);
    }
}

class SingleLinkedList{
    public Node head = new Node();  //head為頭節點不存放任何的資料,只是充當一個指向連結串列中真正存放資料的第一個節點的作用
    
    class Node{
        public int value;
        public Node next;
        public Node() {
            this.next = null;
        }
        public Node(int value) {
            this.value = value;
            this.next = null;
        }
    }
    
    public void add(int value) {//增加節點 尾插法
        if(head.next == null) {
            head.next = new Node(value);
            return;
        }
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
        }
        tempNode.next = new Node(value);
    }
    
    public int findMiddle(){
        Node slowNode = head;
        Node fastNode = head;
        while(fastNode!=null&&fastNode.next!=null) {
            fastNode = fastNode.next.next;
            slowNode = slowNode.next;
        } 
        return slowNode.value;
    }
}

執行如下:

判斷是否為迴圈連結串列

public class test {
    public static void main(String[] args) {
         int[] arr = {5,2,7,4,9,3,1};
         SingleLinkedList singleLinkedList = new SingleLinkedList();
         for(int i=0;i<arr.length;i++){
             singleLinkedList.add(arr[i]);
         }
         Boolean hasCycle = singleLinkedList.hasCycle();
         System.out.println(hasCycle);
    }
}

class SingleLinkedList{
    public Node head = new Node();  //head為頭節點不存放任何的資料,只是充當一個指向連結串列中真正存放資料的第一個節點的作用
    
    class Node{
        public int value;
        public Node next;
        public Node() {
            this.next = null;
        }
        public Node(int value) {
            this.value = value;
            this.next = null;
        }
    }
    
    public void add(int value) {//增加節點 尾插法
        if(head.next == null) {
            head.next = new Node(value);
            return;
        }
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
        }
        tempNode.next = new Node(value);
    }
    
    public void printLink() {//遍歷連結串列
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
            System.out.print(tempNode.value+" ");
        }
    }
    
    public boolean hasCycle() {
         if(head == null) {
             return false;
         }
         Node slowNode = head;
         Node fastNode = head;
         while(slowNode!=null&&fastNode!=null&&fastNode.next!=null) {
             slowNode = slowNode.next;
             fastNode = fastNode.next.next;
             if(slowNode == fastNode) {
                 return true;
             }
         }
         return false;
    }    
}

執行結果如下:

連結串列排序

public class test {
    public static void main(String[] args) {
         int[] arr = {5,2,7,4,9,3,1};
         SingleLinkedList singleLinkedList = new SingleLinkedList();
         for(int i=0;i<arr.length;i++){
             singleLinkedList.add(arr[i]);
         }
         singleLinkedList.sortList();
         singleLinkedList.printLink();
    }
}

class SingleLinkedList{
    public Node head = new Node();  //head為頭節點不存放任何的資料,只是充當一個指向連結串列中真正存放資料的第一個節點的作用
    
    class Node{
        public int value;
        public Node next;
        public Node() {
            this.next = null;
        }
        public Node(int value) {
            this.value = value;
            this.next = null;
        }
    }
    
    public void add(int value) {//增加節點 尾插法
        if(head.next == null) {
            head.next = new Node(value);
            return;
        }
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
        }
        tempNode.next = new Node(value);
    }
    
    public void printLink() {//遍歷連結串列
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
            System.out.print(tempNode.value+" ");
        }
    }
    
    public void sortList() {
        quickSort(head, null);
    }

    private void quickSort(Node low, Node high) {
        if(low == high) {
            return;
        }
        Node pt = partition(low,high);
        quickSort(low,pt);
        quickSort(pt.next,high);
    }

    private Node partition(Node low, Node high) {
        int pivotKey = low.value;
        Node p1 = low; Node p2 = low.next;
        while(p2!=high) {
            if(p2.value < pivotKey) {
                p1 = p1.next;
                
                int temp = p1.value;
                p1.value = p2.value;
                p2.value = temp;
            }
            p2 = p2.next;
        }
        if(p1!=head) {
            int temp = p1.value;
            p1.value = low.value;
            low.value = temp;
        }
        return p1;
    }
}

執行結果如下:

合併兩個已排序連結串列

public class test {
    public static void main(String[] args) {
         int[] arr1 = {1,4,7};
         int[] arr2 = {2,3,5};
         SingleLinkedList singleLinkedList1 = new SingleLinkedList();
         SingleLinkedList singleLinkedList2 = new SingleLinkedList();
         for(int i=0;i<arr1.length;i++){
             singleLinkedList1.add(arr1[i]);
         }
         for(int i=0;i<arr2.length;i++){
             singleLinkedList2.add(arr2[i]);
         }
         Node newNode = singleLinkedList1.merge(singleLinkedList1.head.next,singleLinkedList2.head.next);
         while(newNode!=null) {
             System.out.print(newNode.value+" ");
             newNode = newNode.next;
         }
    }
}
class Node{
    public int value;
    public Node next;
    public Node() {
        this.next = null;
    }
    public Node(int value) {
        this.value = value;
        this.next = null;
    }    
}

class SingleLinkedList{
    public Node head = new Node();  //head為頭節點不存放任何的資料,只是充當一個指向連結串列中真正存放資料的第一個節點的作用
    public void add(int value) {//增加節點 尾插法
        if(head.next == null) {
            head.next = new Node(value);
            return;
        }
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
        }
        tempNode.next = new Node(value);
    }
    
    public Node merge(Node head1,Node head2) {
        if(head1 == null){
            return head2;
        }
        if(head2 == null){
            return head1;
        }
        Node newhead = null;
        if(head1.value <= head2.value){
            newhead = head1;
            newhead.next = merge(head1.next,head2);
        }else{
            newhead = head2;
            newhead.next = merge(head1,head2.next);
        }
        return newhead;
    }
    
}

執行結果為:

刪除倒數第N個節點

public class test {
    public static void main(String[] args) {
         int[] arr = {5,2,7,4,9,3,1};
         SingleLinkedList singleLinkedList = new SingleLinkedList();
         for(int i=0;i<arr.length;i++){
             singleLinkedList.add(arr[i]);
         }
         singleLinkedList.removeNthFromEnd(2);
         singleLinkedList.printLink();
    }
}

class SingleLinkedList{
    public Node head = new Node();  //head為頭節點不存放任何的資料,只是充當一個指向連結串列中真正存放資料的第一個節點的作用
    
    class Node{
        public int value;
        public Node next;
        public Node() {
            this.next = null;
        }
        public Node(int value) {
            this.value = value;
            this.next = null;
        }
    }
    
    public void add(int value) {//增加節點 尾插法
        if(head.next == null) {
            head.next = new Node(value);
            return;
        }
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
        }
        tempNode.next = new Node(value);
    }
    
    public void printLink() {//遍歷連結串列
        Node tempNode = head;
        while(tempNode.next!=null) {
            tempNode = tempNode.next;
            System.out.print(tempNode.value+" ");
        }
    }
    
    public void removeNthFromEnd(int n) {
        if(n<=0) {
            return;
        }
        Node dummyNode = head.next;
        Node preDeleteNode = head;
        
        for(int i=0;i<n;i++) {
            if(dummyNode == null) {
                return;
            }
            dummyNode = dummyNode.next;
        }
        while(dummyNode!=null) {
            dummyNode = dummyNode.next;
            preDeleteNode = preDeleteNode.next;
        }
        preDeleteNode.next = preDeleteNode.next.next;
    }
}

執行結果:

判斷兩個連結串列是否相交

public Node getIntersectionNode(Node headA, Node headB) {
    if (headA == null || headB == null) {
        return null;
    }

    Node currA = headA;
    Node currB = headB;
    int lengthA = 0;
    int lengthB = 0;

    // 讓長的先走到剩餘長度和短的一樣
    while (currA != null) {
        currA = currA.next;
        lengthA++;
    }
    while (currB != null) {
        currB = currB.next;
        lengthB++;
    }

    currA = headA;
    currB = headB;
    while (lengthA > lengthB) {
        currA = currA.next;
        lengthA--;
    }
    while (lengthB > lengthA) {
        currB = currB.next;
        lengthB--;
    }
    
    // 然後同時走到第一個相同的地方
    while (currA != currB) {
        currA = currA.next;
        currB = currB.next;
    }
    // 返回交叉開始的節點
    return currA;
}