数据结构与算法(五)

上一篇我们手动实现了单向循环链表,今天我们实现一个双向循环链表。

import java.util.Objects;

/**

 * 简单实现双向循环链表,双向循环链表与单向循环链表的区别是

 * 单向循环链表只能通过当前节点访问下一节点,

 * 双向循环链表可以通过当前节点访问上个节点和下个节点

 */

public class MyDoubleCircleLink {

    private int size;

    Node head;

    Node tail;

    /**

     * 在链表尾部插入一个元素

     * @param data 要插入的数据

     */

    public void add(Object data){

        Node newNode = new Node(data);

        if(head==null){

            newNode.next = newNode;

            newNode.prev = newNode;

            head = tail = newNode;

        }else{

            tail.next = newNode;

            newNode.next = head;

            head.prev = newNode;

            newNode.prev = tail;

            tail = newNode;

        }

        size++;

    }

    /**

     * 在链表头部插入一个元素

     * @param data 要插入的数据

     */

    public void addHead(Object data){

        Node newNode = new Node(data);

        if(head==null){

            newNode.next = newNode;

            newNode.prev = newNode;

            head = tail = newNode;

        }else{

            tail.next=newNode;

            newNode.next=head;

            head.prev = newNode;

            newNode.prev = tail;

            head=newNode;

        }

        size++;

    }

    /**

     * 在链表指定位置插入一个元素(有两种场景,一种是指定index,一种是指定data,可以做一个重载)

     * @param index 指定下标

     * @param data 要插入的数据

     */

    public void insert(int index,Object data){

        Node newNode = new Node(data);

        if(index>=size||index<0){

            throw new IndexOutOfBoundsException("给定的下标超出链表长度或格式不正确");

        }else{

            if(index==0){//在下标为零的位置插入,就是从头部插入

                addHead(data);

            }else{

                Node temp=head;

                for(int i = 0;i<index-1;i++){

                    temp = temp.next;

                }

                temp.next.prev = newNode;

                newNode.next = temp.next;

                temp.next = newNode;

                newNode.prev = temp;

                size++;

            }

        }

    }

    /**

     * 在目标数据前面插入一个元素

     * @param target 目标数据

     * @param data 要插入的数据

     */

    public void insert(Object target,Object data){

        Node newNode = new Node(data);

        if(Objects.equals(target,head.data)){

            addHead(data);

            return;

        }else {

            for (Node temp = head; temp.next != null; temp = temp.next) {

                if (Objects.equals(target, temp.next.data)) {//这里的next可以控制元素插入到目标元素之前还是之后

                    newNode.next = temp.next;

                    temp.next = newNode;

                    size++;

                    return;

                }

            }

        }

        //throw new FindException("指定的目标数据不存在");

        System.out.println("指定的目标数据不存在");

    }

    /**

     * 从链表尾部删除一个元素

     */

    public void deleteTail(){

        for(Node temp = head; temp!=tail; temp=temp.next){

            if(temp.next==tail){

                temp.next=head;

                head.prev = temp;

                tail = temp;

                size--;

                return;

            }

        }

    }

    /**

     * 从链表头部删除一个元素

     */

    public void deleteHead(){

        tail.next = head.next;

        head.next.prev = tail;

        head = head.next;

        size--;

    }

    /**

     * 从链表指定位置删除一个元素(两种场景,一种是删除指定下标位置的元素,一种是删除值为目标值的元素(只删第一次出现的位置))

     * @param index 指定下标

     */

    public void delete(int index){

        if(index >= size||index <0 ){

            throw new IndexOutOfBoundsException("给定的下标超出链表长度或格式不正确");

        }else{

            if(index==0){

                deleteHead();

            }else if(index == size-1){

                deleteTail();

            }else{

                int i=0;

                for(Node temp = head; temp!=tail; temp = temp.next){

                    if(i==index-1){

                        temp.next.next.prev = temp;

                        temp.next=temp.next.next;

                        size--;

                        return;

                    }

                    i++;

                }

            }

        }

    }

    /**

     * 删除值为data的元素(一次)

     * @param data

     */

    public void delete (Object data){

        if(Objects.equals(data,head.data)){

            deleteHead();

            return;

        }else {

            for(Node temp = head; temp!=tail; temp = temp.next){

                if (Objects.equals(data, temp.next.data)) {

                    if(temp.next==tail){

                        deleteTail();

                        return;

                    }else {

                        temp.next.next.prev = temp;

                        temp.next = temp.next.next;

                        size--;

                        return;

                    }

                }

            }

        }

        System.out.println("指定的目标数据不存在");

    }

    /**

     * 修改链表中指定位置元素的值

     * @param index 指定下标

     * @param data 修改后的值

     */

    public void update(int index,Object data){

        if(index>=size||index<0){

            throw new IndexOutOfBoundsException("指定下标超出列表长度或下标格式不正确");

        }else if(index == 0){

            head.data = data;

        }else{

            Node temp = head;

            for(int i = 0;i<size;i++){

                if(i==index-1){

                    temp.next.data = data;

                }

                temp = temp.next;

            }

        }

    }

    /**

     * 获取链表指定位置元素的值

     *

     * @param index 指定下标

     */

    public Object get(int index){

        if(index>=size||index<0){

            throw new IndexOutOfBoundsException("指定下标超出列表长度或下标格式不正确");

        }else if(index == 0){

            return head.data;

        }else{

            Node temp = head;

            for(int i = 0;i<size;i++){

                if(i==index-1){

                    return temp.next.data;

                }

                temp = temp.next;

            }

        }

        return null;

    }

    public void print(){

        Node tempNode=head;

        while(tempNode!=tail){

            System.out.println(tempNode.data);

            tempNode = tempNode.next;

        }

        System.out.println(tail.data);

    }

    //获取链表元素个数

    public int size(){

        return size;

    }

    class Node{

        Object data;

        Node next;//下一节点

        Node prev;//上一节点

        Node(Object data){

            this.data = data;

            this.next = null;

            this.prev = null;

        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值