1. 程式人生 > 其它 >Java資料結構與演算法筆記——單向連結串列和雙端連結串列

Java資料結構與演算法筆記——單向連結串列和雙端連結串列

技術標籤:資料結構與演算法

文章目錄

連結串列

連結串列是一種常見的基礎資料結構,是一種線性表,但是連結串列不會按線性的順序儲存資料,而是在每個節點裡存到下一個節點的指標

優點:
使用連結串列結構可以克服陣列需要預先知道資料大小的缺點,連結串列結構可以充分地利用計算機記憶體空間,實現靈活的記憶體動態管理。

缺點:
連結串列失去了陣列隨機讀取的優點(沒有下標),同時連結串列由於增加了節點的指標域,空間開銷比較大。

單向連結串列

單向連結串列簡介

單向連結串列是連結串列中結構最簡單的。
一個單鏈表的節點(Node)分為兩個部分,第一部分儲存或者顯示關於節點的資訊,另一個部分儲存下一個節點的地址。
最後一個節點儲存地址的部分指向空值。連結串列有一個頭結點。
在這裡插入圖片描述
查詢:
從第一個節點開始遍歷
刪除:
刪除節點,把上一個節點的指標指向下一節點(速度比陣列快)
插入:
在頭部插入

java實現單向連結串列

package link;

public class SingleLinkTest {
    public static void main(String[] args) {
        SingleLinkedList singleLinkedList =
new SingleLinkedList(); singleLinkedList.addHead('A'); singleLinkedList.addHead('B'); singleLinkedList.addHead('C'); singleLinkedList.addHead('D'); //列印連結串列 singleLinkedList.display(); System.out.println(singleLinkedList.delete('A')); singleLinkedList.
display(); System.out.println(singleLinkedList.isEmpty()); System.out.println(singleLinkedList.deleteHead()); } } //封裝單向連結串列的類 class SingleLinkedList{ private int size; //連結串列的節點數 private Node head; // head是頭結點的指標,引入了一個新型別,node //構造方法 public SingleLinkedList(){ size = 0; head = null; } //向連結串列中新增節點(新增到頭部) public Object addHead(Object data){ Node newNode = new Node(data); if(size == 0){ //空連結串列 head = newNode; }else { //非空連結串列 newNode.next = head; head = newNode; } size ++; return newNode; } //連結串列刪除頭結點,預設連結串列中是有節點的 public Object deleteHead(){ Object obj = head.data; head = head.next; size--; return obj; } //查詢指定資料所對應的節點物件 public Node find(Object data){ Node curent = head; int tmpSize = size; while (tmpSize > 0){ if (data.equals(curent.data)){ //找到了物件 return curent; }else { curent = curent.next; } tmpSize--; } return null; //如果找不到 } //判斷連結串列是不是空連結串列 public boolean isEmpty(){ return size==0; } //刪除指定節點,刪除成功返回true,失敗返回false public boolean delete(Object value){ if(isEmpty()){ //空表 return false; } //不是空表 Node current = head; Node previous = head;//上一個變數 while (!value.equals(current.data)){ if (current.next == null){ //已經掃描到了尾結點,且沒找到資料 return false; }else{ //還沒到尾結點 previous = current; current = current.next; } } // 迴圈終止了,還會繼續執行下面的語句,證明已經找到了要找的節點 //刪除找到的節點 if(current == head){ head = head.next; size --; }else{ previous.next = current.next; size --; } return true; } //遍歷輸出所有node資訊 public void display(){ if (size>0){ //不是空的 Node current = head; int tmpSize = size; if (tmpSize == 1){ System.out.println("[" + head.data + "]"); return; // 結束掉方法 } while (tmpSize>0){ if (current == head){ System.out.print("[" + current.data + "->"); }else if(current.next == null){ //最後一個節點 System.out.print(current.data + "]"); }else { System.out.print(current.data + "->"); } tmpSize --; current = current.next; } System.out.println();//輸出一個換行符 }else { //空列表 System.out.println("[]"); } } //定義一個私有類 private class Node{ private Object data; //封裝在節點裡的資料 private Node next; //指標,指向下一個節點 //構造方法 public Node(Object data){ this.data = data; } @Override public String toString() { return "Node [data=" + data + ", next=" + next + "]"; } } }

雙端連結串列

雙端連結串列簡介

對於單向連結串列,我們如果想在尾部新增一個節點,那麼必須從頭部一直遍歷到尾部,找到尾結點,然後在尾結點後面插入一個節點。
這樣操作很慢,如果我們在設計連結串列的時候多個對尾結點的引用,那麼會簡單很多

java實現雙端連結串列

package link;

public class DoubleLinkedListTest {
    public static void main(String[] args) {
        DoubleLinkedList link = new DoubleLinkedList();
        link.addHead(1);
        link.addHead(0);
        link.addTail(2);
        link.addTail(3);
        link.addTail(2);
        link.display();

        link.delete(2);
        link.display();
        System.out.println(link.deleteHead());
        link.display();

        while(!link.isEmpty()){
            System.out.println(link.deleteTail());
        }

    }
}

class DoubleLinkedList{
    private int size; //連結串列的節點數
    private Node head; // head是頭結點的指標,引入了一個新型別,node
    private Node tail; //指向尾結點的指標

    //構造方法
    public DoubleLinkedList(){
        size = 0;
        head = null;
        tail = null;
    }

    //向連結串列中新增節點(新增到頭部)
    public Object addHead(Object data){
        Node newNode = new Node(data);
        if(size == 0){
            //空連結串列
            head = newNode;
            tail = newNode;
        }else {
            //非空連結串列
            newNode.next = head;
            head = newNode;
        }
        size ++;
        return newNode;
    }

    //新增尾結點
    public Object addTail(Object data){
        Node newNode = new Node(data);
        if(size == 0) {
            //空連結串列
            head = newNode;
            tail = newNode;
        }else {
            tail.next = newNode;
            tail = newNode;
        }
        size ++;
        return newNode;
    }

    //連結串列刪除頭結點
    public Object deleteHead(){
        Object obj = null;
        if(size == 0){
            //空連結串列
            return obj;
        }else if(size == 1){
            //連結串列中只有一個節點
            obj = head.data;
            head = null;
            tail = null;
            size --;
        }else{
            obj = head.data;
            head =head.next;
            size --;
        }

        return obj;
    }

    //刪除尾部節點
    public Object deleteTail(){
        Object obj = null;
        if(size == 0){
            //空連結串列
            return obj;
        }else if(size == 1) {
            //連結串列中只有一個節點
            obj = tail.data;
            head = null;
            tail = null;
            size --;
        }else {
            obj = tail.data;
//            int tmp = 1;
            Node tmpNode = head;
//            while (tmp<size-1){
//                tmpNode = tmpNode.next;
//                tmp ++;
//            }

            while (tmpNode.next != tail){
                tmpNode = tmpNode.next;
            }

            tail = tmpNode;
            tail.next = null;
            size --;
        }

        return obj;
    }

    //判斷連結串列是不是空連結串列
    public boolean isEmpty(){
        return size==0;
    }

    //刪除指定節點,刪除成功返回true,失敗返回false
    public boolean delete(Object value){
        if(isEmpty()){
            //空表
            return false;
        }

        //不是空表
        Node current = head;
        Node previous = head;//上一個變數
        while (!value.equals(current.data)){
            if (current.next == null){
                //已經掃描到了尾結點,且沒找到資料
                return false;
            }else{
                //還沒到尾結點
                previous = current;
                current = current.next;
            }
        }
        // 迴圈終止了,還會繼續執行下面的語句,證明已經找到了要找的節點
        //刪除找到的節點
        if(size == 1){
            head = null;
            tail = null;
        }else if(current == head){
            head = head.next;
        }else if(current == tail){
            previous.next = null;
            tail = previous;
        }else {
            previous.next = current.next;
        }
        size --;
        return true;
    }

    //遍歷輸出所有node資訊
    public void display(){
        if (size>0){
            //不是空的
            Node current = head;
            int tmpSize = size;
            if (tmpSize == 1){
                System.out.println("[" + head.data + "]");
                return; // 結束掉方法
            }
            while (tmpSize>0){
                if (current == head){
                    System.out.print("[" + current.data + "->");
                }else if(current.next == null){
                    //最後一個節點
                    System.out.print(current.data + "]");
                }else {
                    System.out.print(current.data + "->");
                }
                tmpSize --;
                current = current.next;
            }
            System.out.println();//輸出一個換行符
        }else {
            //空列表
            System.out.println("[]");
        }
    }

    //獲取節點個數
    public int getSize(){
        return size;
    }

    //定義一個私有類
    private class Node{
        private Object data; //封裝在節點裡的資料
        private Node next; //指標,指向下一個節點

        //構造方法
        public Node(Object data){
            this.data = data;
        }

        @Override
        public String toString() {
            return "Node [data=" + data + ", next=" + next + "]";
        }
    }

}

基於雙端連結串列實現佇列

佇列:隊尾插入,隊頭刪除。先進先出。

package link;

public class QueueDoubleLinkedListTest {
    public static void main(String[] args) {
        QueueDoubleLinkedList queueDoubleLinkedList = new QueueDoubleLinkedList();
        queueDoubleLinkedList.insert(1);
        queueDoubleLinkedList.insert(2);
        queueDoubleLinkedList.insert(3);
        queueDoubleLinkedList.insert(4);

        queueDoubleLinkedList.display();

        System.out.println(queueDoubleLinkedList.delete());
        queueDoubleLinkedList.display();
        System.out.println(queueDoubleLinkedList.isEmpty());
        System.out.println(queueDoubleLinkedList.getSize());
    }
}

class QueueDoubleLinkedList{
    private DoubleLinkedList doubleLinkedList;

    public QueueDoubleLinkedList(){
        doubleLinkedList = new DoubleLinkedList();
    }

    //插入(連結串列尾部插入)
    public void insert(Object data){
        doubleLinkedList.addTail(data);
    }

    //刪除(連結串列頭部刪除)
    public Object delete(){
        return doubleLinkedList.deleteHead();
    }

    //是否為空
    public boolean isEmpty(){
        return doubleLinkedList.isEmpty();
    }

    //獲取佇列元素個數
    public int getSize(){
        return doubleLinkedList.getSize();
    }

    //顯示佇列元素
    public void display(){
        doubleLinkedList.display();
    }
}