java数据结构--双链表的设计与实现

package com.zjp.structures;

/**
 * 带头节点(不带数据)的双链表
 */
public class DoubleLinkedList<T> {
    DNode<T> head;
    DNode<T> tail;

    public DoubleLinkedList() {
        //初始化头节点
        this.head = this.tail = new DNode<T>();
    }

    /**
     * 传入一个数组,转换成一个链表
     *
     * @param arr
     */
    public DoubleLinkedList(T[] arr) {
        this();
        if (arr != null && arr.length > 0) {
            head.next = new DNode<T>(arr[0]);
            tail = head.next;
            tail.prev = head;
            int j = 1;
            while (j < arr.length) {
                tail.next = new DNode<T>(arr[j++]);
                tail.next.prev = tail;
                tail = tail.next;
            }
        }
    }

    /**
     * 插入节点
     *
     * @param index
     * @param data
     * @return
     */
    public boolean add(int index, T data) {
        if (index < 0 || data == null) {
            throw new NullPointerException("index<0||data == null");
        }
        //查找要插入节点位置的前一个节点
        int j = 0;
        DNode front = this.head;
        while (j < index && front.next != null) {
            j++;
            front = front.next;
        }
        //创建需要插入的节点,让其前一个节点指向front,后一个节点指向front.next
        DNode<T> q = new DNode<T>(data, front, front.next);
        //空双链表插入和尾部插入,无需次操作
        if (front.next != null) {
            //更改front.next的前几指针
            front.next.prev = q;
        }
        //更改front的后继指针
        front.next = q;
        //在尾部插入时需要更改tail指向
        if (front == this.tail) {
            this.tail = q;
        }
        return true;
    }

    /**
     * 尾部添加
     *
     * @param data
     * @return
     */
    public boolean add(T data) {
        if (data == null) {
            return false;
        }
        //创建要插入的节点
        DNode<T> p = new DNode<T>(data, tail, null);
        tail.next = p;
        tail = p;
        return true;
    }

    /**
     * 根据下标删除节点
     * 1,头删除
     * 2,中间删除
     * 3,尾部删除,更新tail指向
     *
     * @param index
     * @return
     */
    public T remove(int index) {
        int size = length();
        T temp = null;
        if (index < 0 || index >= size || isEmpty()) {
            return temp;
        }
        //寻找要删除的节点
        DNode<T> p = this.head;
        int j = 0;
        while (j <= index && p != null) {
            p = p.next;
            j++;
        }
        //更新后继节点,当双链表只有一个节点或者在尾部删除时,无需此操作
        if (p.next != null) {
            p.next.prev = p.prev;
        }
        //更新前驱节点
        p.prev.next = p.next;
        //如果删除的是尾节点,更新尾节点的指向
        if (p == tail) {
            this.tail = p.prev;
        }
        temp = p.data;
        return temp;
    }

    /**
     * 根据data删除节点
     *
     * @param data
     * @return
     */
    public boolean removeAll(T data) {
        boolean isRemove = false;
        if (data == null) {
            return isRemove;
        }
        //起始节点
        DNode p = this.head.next;
        while (p != null) {
            if (p.data.equals(data)) {
                //如果是尾节点
                if (p == tail) {
                    //更新尾节点的指向
                    tail = p.prev;
                    p.prev = null;
                    tail.next = null;
                } else {//如果不是尾节点
                    p.next.prev = p.prev;
                    p.prev.next = p.next;
                }
                isRemove = true;
            }
            //继续查找
            p = p.next;
        }
        return isRemove;
    }

    /**
     * 求双链表的长度
     *
     * @return
     */
    public int length() {
        int length = 0;
        DNode pre = head.next;
        while (pre != null) {
            pre = pre.next;
            length++;
        }
        return length;
    }

    /**
     * 判断双链表是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return head.next == null;
    }

    /**
     * 双链表的查值操作
     *
     * @param index
     * @return
     */
    public T get(int index) {
        if (index >= 0) {
            //起始节点
            DNode<T> p = this.head.next;
            int i = 0;
            //查找节点
            while (i < index && p != null) {
                i++;
                p = p.next;
            }
            if (p != null) {
                return p.data;
            }
        }
        return null;
    }

    /**
     * 双链表的替换值操作
     *
     * @param index
     * @param data
     * @return
     */
    public T set(int index, T data) {
        T old = null;
        if (index >= 0 && data != null) {
            DNode<T> p = this.head.next;
            int j = 0;
            //寻找要替换的节点
            while (j < index && p != null) {
                j++;
                p = p.next;
            }
            if (p != null) {
                old = p.data;
                //替换数据
                p.data = data;
            }
        }
        return old;
    }

    /**
     * 清空链表
     */
    public void clear() {
        this.head.next = null;
        this.tail = this.head;
    }

    public boolean contains(T data) {
        if (data == null) {
            return false;
        }
        DNode p = head.next;
        while (p != null) {
            if (p.data.equals(data)) {
                return true;
            } else {
                p = p.next;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        String s = "{";
        //起始节点
        DNode p = head.next;
        while (p != null) {
            s += p.data;
            p = p.next;
            if (p != null) {
                s += ",";
            }
        }
        return s + "}";
    }

    //测试方法
    public static void main(String[] args) {
        String[] arr = {"A", "B", "C", "D", "E", "F"};
        DoubleLinkedList<String> doubleLinkedList = new DoubleLinkedList<String>(arr);
        boolean a = doubleLinkedList.contains("A");
        System.out.println(a);
        doubleLinkedList.remove(0);
        boolean a1 = doubleLinkedList.contains("A");
        System.out.println(a1);
        System.out.println(doubleLinkedList.length());
        doubleLinkedList.set(3, "D");
        System.out.println(doubleLinkedList.get(2));
        System.out.println(doubleLinkedList.toString());
        boolean a2 = doubleLinkedList.removeAll("D");
        System.out.println(a2);
        System.out.println(doubleLinkedList.toString());
        doubleLinkedList.clear();
        System.out.println(doubleLinkedList.toString());
    }

    class DNode<T> {
        //数据域
        T data;
        //前驱节点
        DNode prev;
        //后继节点

        DNode next;

        public DNode(T data, DNode prev, DNode next) {
            this.data = data;
            this.prev = prev;
            this.next = next;
        }

        public DNode() {
            this(null, null, null);
        }

        public DNode(T data) {
            this(data, null, null);
        }
        @Override
        public String toString() {
            return this.data.toString();
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值