首頁 > Java > java教程 > 主體

Java雙向鍊錶的增刪改查怎麼實現

王林
發布: 2023-05-12 13:25:06
轉載
1362 人瀏覽過

一、認識雙向鍊錶

單向鍊錶不僅保存了目前的結點值,還保存了下一個結點的位址

Java雙向鍊錶的增刪改查怎麼實現

##雙向鍊錶不僅保存了目前節點的值,還保存了上一個結點的位址和下一個結點的位址

Java雙向鍊錶的增刪改查怎麼實現

定義一個雙向鍊錶的結點類:

結點中既要保存目前節點的值,還要保存此節點的前驅節點的位址和此節點的後繼節點的位址

class DoubleNode{
    public DoubleNode next;
    DoubleNode prev;
    int val;
    DoubleNode tail;

    public DoubleNode() {}

    public DoubleNode(int val) {
        this.val = val;
    }

    public DoubleNode(DoubleNode prev, int val, DoubleNode tail) {
        this.prev = prev;
        this.val = val;
        this.tail = tail;
    }
}
登入後複製

定義一個雙向鍊錶類別:

既可以從前向後,也可以從後向前,所以在這個類別中,即保存一下頭結點,也保存一下尾結點的值

public class DoubleLinkedList {
    private int size;
    private DoubleNode head;
    private DoubleNode tail;
}
登入後複製

二、雙向鍊錶的增刪改查

1.插入

頭插
在目前鍊錶的頭部插入一個節點,讓目前鍊錶的頭結點head前驅指向要插入的節點node,然後讓node的後繼指向head,然後讓head = node,讓node成為鍊錶的頭結點

Java雙向鍊錶的增刪改查怎麼實現

程式碼如下:

/**
     * 头插
     */
    public void addFirst(int val){
        DoubleNode node = new DoubleNode(val);
        if (head == null){
            head = tail = node;
        }else{
            node.next = head;
            head.prev = node;
            head = node;
        }
        size++;
    }
登入後複製

尾插
和頭插一樣,只不過在鍊錶的尾部插入

Java雙向鍊錶的增刪改查怎麼實現

程式碼如下:

 public void addLast(int val){
        DoubleNode node = new DoubleNode(val);
        if (head == null){
            head = tail =node;
        }else{
            tail.next = node;
            node.prev = tail;
            tail = node;
        }
        size++;
    }
登入後複製

在index位置插入

#在索引為index的位置插入值為val的節點:

插入還是要找前驅節點,但雙向鍊錶找前驅節點比單向鍊錶找前驅節點要靈活很多,單向鍊錶只能從頭走到尾,假如此時有100個節點,要在索引為98的位置插入節點,那麼雙向鍊錶就可以從尾結點開始找,會方便很多

#如何判斷從前向後找,還是從後向前找?

  • 1.index < size / 2 – >從前向後找,插入位置在前半部

  • 2 .index > size / 2 – >從後向前找,插入位置在後半部

Java雙向鍊錶的增刪改查怎麼實現

##程式碼如下:

/**
     * 在index位置插入
     * @param index
     * @param val
     */
    public void add(int index,int val){
        DoubleNode cur = new DoubleNode(val);
        if (index < 0 || index > size){
            System.err.println("add index illegal");
            return;
        }else{
            if (index == 0){addFirst(val);}
            else if (index == size){addLast(val);}
            else{
                DoubleNode prev = node(index-1);
                DoubleNode next = prev.next;
                cur.next = next;
                next.prev = cur;
                prev.next = cur;
                cur.prev = prev;
            }
        }
        size++;
    }
/**
     * 根据索引值找到对应的结点
     * @param index
     * @return
     */
    private DoubleNode node(int index){
        DoubleNode x = null;
        if (index < size/2){
            x = head;
            for (int i = 0; i < index; i++) {
                x = x.next;
            }
        }else{
            x = tail;
            for (int i = size - 1; i > index ; i--) {
                x = x.prev;
            }
        }
        return x;
    }
登入後複製
2.修改

程式碼如下:

/**
     * 修改双向链表index位置的结点值为newVal
     */
    public int set(int index,int newVal){
        DoubleNode dummyHead = new DoubleNode();
        dummyHead.next = head;
        DoubleNode prev = dummyHead;
        DoubleNode cur = prev.next;
        if (index < 0 || index > size - 1){
            System.err.println("set index illegal");
        }else{
            for (int i = 0; i < index; i++) {
                prev = prev.next;
                cur = cur.next;
            }
        }
        int oldVal = cur.val;
        cur.val = newVal;
        return oldVal;
    }
登入後複製
3.查詢

程式碼如下:

 /**
     * 查询index位置的结点值
     */
    public int get(int index){
        DoubleNode dummyHead = new DoubleNode();
        dummyHead.next = head;
        DoubleNode prev = dummyHead;
        DoubleNode cur = prev.next;
        if (index < 0 || index > size - 1){
            System.err.println("get index illegal");
        }else{
            for (int i = 0; i < index; i++) {
                prev = prev.next;
                cur = cur.next;
            }
        }
        return cur.val;
    }
登入後複製
4.刪除

刪除index位置的節點

#程式碼如下:

//删除链表index位置的结点
    public void removeIndex(int index){
        if (index < 0 || index > size - 1){
            System.err.println("remove index illegal");
            return;
        }
        DoubleNode cur = node(index);
        unlink(cur);
    }
 /**
     * 删除当前双向链表的node结点
     * 分治法
     * @param node
     */
    private void unlink (DoubleNode node){
        DoubleNode prev = node.prev;
        DoubleNode successor = node.next;
        //1.先处理node的前半部分
        if (prev == null){
            head = successor;
        }else{
            //前驱不为空的情况
            prev.next = successor;
            node.prev = null;
        }
        if (successor == null){
            tail = prev;
        }else{
            successor.prev = prev;
            node.next = null;
        }
        size--;
    }
登入後複製
頭刪

呼叫刪除任意位置的節點即可

程式碼如下:

//头删
    public void removeFirst(){
      removeIndex(0);
    }
登入後複製
尾刪

呼叫刪除任意位置的節點即可

程式碼如下:

//尾删
    public void removeLast(){
        removeIndex(size - 1);
    }
登入後複製
刪除第一個值為val的節點

程式碼如下:

//删除第一个值为val的结点
    public void removeValOnce(int val){
        if (head == null){
            return;
        }
        for (DoubleNode x = head;x != null;x = x.next){
            if (x.val == val){
                unlink(x);
                break;
            }
        }
    }

 /**
     * 删除当前双向链表的node结点
     * 分治法
     * @param node
     */
    private void unlink (DoubleNode node){
        DoubleNode prev = node.prev;
        DoubleNode successor = node.next;
        //1.先处理node的前半部分
        if (prev == null){
            head = successor;
        }else{
            //前驱不为空的情况
            prev.next = successor;
            node.prev = null;
        }
        if (successor == null){
            tail = prev;
        }else{
            successor.prev = prev;
            node.next = null;
        }
        size--;
    }
登入後複製
刪除所有值為val的值

程式碼如下:

//删除链表中所有值为val的结点
    public void removeAllVal(int val){
        for (DoubleNode x = head;x != null;){
            if (x.val == val){
                //暂存一下x的下一个结点
                DoubleNode next = x.next;
                unlink(x);
                x = next;
            }else{
                //val不是待删除的元素
                x = x.next;
            }
        }
    }
 /**
     * 删除当前双向链表的node结点
     * 分治法
     * @param node
     */
    private void unlink (DoubleNode node){
        DoubleNode prev = node.prev;
        DoubleNode successor = node.next;
        //1.先处理node的前半部分
        if (prev == null){
            head = successor;
        }else{
            //前驱不为空的情况
            prev.next = successor;
            node.prev = null;
        }
        if (successor == null){
            tail = prev;
        }else{
            successor.prev = prev;
            node.next = null;
        }
        size--;
    }
登入後複製

以上是Java雙向鍊錶的增刪改查怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:yisu.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!