数据结构3:双链表的简单实现

package com.zejian.structures.LinkedList.MyLinked;
 
/**
 * 双链表的工具类
 */
public class DNode<T> {
 
    public T data;//存储的数据
 
    public DNode<T> pre;//前指针
 
    public DNode<T> next;//后指针
 
    //构造方法 创建对象
    public DNode(T data, DNode<T> pre, DNode<T> next) {
        this.data = data;
        this.pre = pre;
        this.next = next;
    }
 
    /**
     * 创建一个前指针、后指针为空的值
     * @param data
     */
    public DNode(T data) {
        this(data,null,null);
    }
 
    /**
     * 创建一个空值
     */
    public DNode() {
        this(null,null,null);
    }
 
    @Override
    public String toString() {
        return this.data.toString();
    }
}


package com.zejian.structures.LinkedList.MyLinked;

public class DoubleLinkedList<T> implements ILinkedList<T> {

    //设置头节点
    private DNode<T> head;
    //设置尾节点
    private DNode<T> tail;

    //构造方法初始化头结点尾节点值
    public DoubleLinkedList() {
        //设置为空值
        this.head=this.tail=new DNode<>();
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    /**
     * 长度
     * @return
     */
    @Override
    public int length() {
        int length=0;
        DNode<T> pre=head.next;
        while (pre!=null){
            length++;
            pre=pre.next;
        }
        return length;
    }

    @Override
    public T get(int index) {
        return null;
    }

    @Override
    public T set(int index, T data) {
        return null;
    }

    /**
     * 插入结点
     * @param index
     * @param data
     * @return
     */
    @Override
    public boolean add(int index, T data) {

        DNode<T> font = this.head;//头节点是一个空节点,尾节点有tail控制
        int j=0;
        //找到插入节点的前一个节点j<index
        while (font.next!=null&&j<index){


            font=font.next;
            j++;
        }

        //创建新的节点,在虚拟机中开辟了内存,创建了对象,
        DNode<T> p = new DNode<>(data, font, font.next);//数据  数据的前节点   数据的后节点  ;传入的对象赋值给新对象的前节点和后节点

        //改变前节点和后节点指针方向,新对象的内存地址赋值
        font.next=p;

        //尾节点或者是头节点不执行此操作
        if (font.next!=null){
        font.next.pre=p;
        }

//        p= font.next;
//        p=font.next.pre;

        //如果是尾节点,更新尾节点
        if (font==tail){

            this.tail=p;
        }




        return false;
    }

    /**
     * 从尾部插入
     * @param data
     * @return
     */
    @Override
    public boolean add(T data) {

        //空节点和头结点已经创建了,可以直接拿来用
        if (data!=null){
        //插入第一个数据
            DNode<T> p = new DNode<>(data, tail, null);//数据  前节点(这时就是头结点;将尾节点赋值给头结点)  后节点(null)

            //改变指针  这时尾节点 所以没有 tail.next.pre=p
            tail.next=p;

            //将最后一个数据赋值尾节点
            this.tail=p;



        }


        return false;
    }

    /**
     * 根据索引删除
     * @param index
     * @return
     */
    @Override
    public T remove(int index) {

        int size=length();
        T temp=null;

        if(index<0||index>=size||isEmpty()){
            return temp;
        }

        DNode<T> removeNode = this.head.next;
        int j=0;
        while (removeNode.next!=null&&j<index){//这时获取的删除的节点

            removeNode=removeNode.next;
            j++;
        }

        //改变指针方向,改变的是已有节点的指针方向
        removeNode.pre.next=removeNode.next;


        //当节点为尾节点或者只有一个节点时
        if (removeNode.next==null){

            removeNode.next.pre=removeNode.pre;
        }


        //如果是尾节点,更新尾节点
        if (removeNode==tail){
            this.tail=removeNode.pre;

        }


        return removeNode.data;
    }






    /**
     * 根据data删除结点,无需像单向链表那样去存储要删除结点的前一个结点
     * 1.头删除
     * 2.中间删除
     * 3.尾部删除,更新tail指向
     * @param data
     * @return
     */
    @Override
    public boolean removeAll(T data) {

        boolean isRemove=false;

        if(data==null||isEmpty())
            return isRemove;

        //注意这里的起点,如果起点为this.head,那么情况区别如同前面的根据index的删除实现
        DNode<T> p=this.head.next;

        //头删除/尾删除/中间删除(size>1),查找所有需要删除的结点
        while (p!=null){

            if(data.equals(p.data)){
                if (p==this.tail){
                    //如果是尾结点
                    this.tail=p.pre;//更新未结点的指向,已经赋好值了,所以tail!=null
                    p.pre=null;//加速gc回收,处理删除信息
                    this.tail.next=null;//将next赋值为空
                }else {
                    //如果是在中间删除,更新前继和后继指针指向
                    p.pre.next=p.next;
                    p.next.pre=p.pre;
                }
                isRemove=true;
                p=p.next;//继续查找
            }else {
                p=p.next;
            }

        }
        return isRemove;
    }

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


    @Override
    public boolean contains(T data) {

        if(data==null){
            return false;
        }

        DNode<T> p=this.head.next;
        while (p!=null){
            if (data.equals(p.data)){
                return true;
            }else {
                p=p.next;
            }
        }

        return false;
    }

    @Override
    public String toString() {
        String str="(";
        DNode<T> pre = this.head.next;
        while (pre!=null)
        {
            str += pre.data;
            pre = pre.next;
            if (pre!=null)
                str += ", ";
        }
        return str+")";
    }

    /**
     * 传入一个数组,转换成链表
     * @param array
     */
    public DoubleLinkedList(T[] array)
    {
        this();
        if (array!=null && array.length>0)
        {
            //头结点的下一个节点赋值   新节点——>头结点
            this.head.next = new DNode<T>(array[0]);
            //赋值给尾节点
            tail =this.head.next;

            //头结点——>新节点
            tail.pre=this.head;
            int i=1;
            while (i<array.length)
            {
                //新节点——>尾节点
                DNode<T> tdNode = new DNode<>(array[i++]);
                tail.next=tdNode;
                //尾节点——>新节点
                tdNode.pre=tail;

                //尾节点重新赋值
                tail = tail.next;
            }
        }
    }
    public static void main(String[] args){

        String[] letters={"A","B","C","D","Z","E","F"};
//        String[] letters={"A"};
        DoubleLinkedList<String> list=new DoubleLinkedList<>(letters);

        System.out.println("list.get(3)->"+list.get(3));
        System.out.println("list:"+list.toString());

        System.out.println("list.add(4,Y)—>"+list.add(0,"Y"));
        System.out.println("list:"+list.toString());
        System.out.println("list.add(Z)—>"+list.add("Z"));
        System.out.println("list:"+list.toString());


        System.out.println("list.contains(Z)->"+list.contains("Z"));
        System.out.println("list.set(4,P)-->"+list.set(4,"P"));
        System.out.println("list:"+list.toString());


        System.out.println("list.remove(6)-->"+list.remove(6));
//        System.out.println("list.remove(Z)->"+list.removeAll("Z"));
        System.out.println("list:"+list.toString());
    }
}


代码不全只是自己记录学习,借鉴:https://blog.csdn.net/javazejian/article/details/52953190;强烈推荐此大神博客。。。

猜你喜欢

转载自blog.csdn.net/qq_38788128/article/details/80911837