Lava链表(双向链表---接口实现)

在Java中连标配的结点需要用类来封装,下面的简单的双向链表实现:

class Node
{
    private Object data;
    private Node next;

    public Node(Object data) {
        this.data = data;
    }

    public Object getData() {
        return data;
    }

    public Node getNext() {
        return next;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public void setNext(Node next) {
        this.next = next;
    }
}
public class Link
{
    public static void main(String[] args)
    {
        Node head=new Node("世界");
        Node first1=new Node("pick");
        Node first2=new Node(1019);
        Node tail=new Node("happy");
        head.setNext(first1);  //在主类中进行链表的链接和插入
        first1.setNext(first2);
        first2.setNext(tail);
        print(head);
    }
    public static  void print(Node node)
    {
        if(node==null)
            return ;
        System.out.println(node.getData());
        node=node.getNext();
        print(node);
    }
}

以上代码是在客户端中进行链表的链接,而客户端中并不用看到具体的链接过程,只需要插入数据或者其他具体操作,所以需要用一个类来进行Node类数据的保存和链表之间的链接;但是客户端只需要进行插入数据等,并不关心是通过何种数据结构实现,但是对于客户端需求有很多数据结构实现,为了操作标准化,定义一个接口。代码如下:

package CODE;


import javafx.beans.binding.ObjectBinding;
import jdk.nashorn.internal.ir.UnaryNode;
import org.omg.CORBA.OBJ_ADAPTER;

import javax.management.ObjectName;

////双向链表
interface Ilink
{
    boolean add(Object data); //添加
    boolean remove(Object data);  //删除数据为data的结点
    void printLink();  //遍历该链表
    int size();  //结点个数
    Object set(int index ,Object newdata);// 把索引index所在位置元素替换为newdata,返回原来数据
    int contains(Object data);//判断data是否在链表中
    Object get(int index);//根据下标返回结点内容
    void clear();//销毁
    Object[] toArray();//将链表转为数组
}
class LinkImpl implements Ilink
{
    private Node head;//头结点
    private Node tail; //尾结点
    private int size; //结点个数

    private class Node  //定义为内部类是一种封装
            //将每个结点定义为私有内部类,目的内部类和外部类可以访问彼此的私有属性,而且客户端不知道每个结点具体情况,
    {
        Node prev;
        private Object data;
        Node next;
        public Node(Node prev, Object data,Node next)  //结点的构造方法
        {
            this.prev=prev;
            this.data=data;
            this.next=next;
        }
    }
    public boolean add(Object data)
    {
        //利用尾插
        Node prev=this.tail;
        Node newnode=new Node(this.tail,data,null);
        if(this.head==null)  //第一次插入时头为为空,将头尾都指向newnode
            this.head=newnode;
        else
        {
            prev.next=newnode;
        }
        this.tail=newnode;
        this.size++;
        return true;
    }
    public boolean remove(Object data)
    {
        if(data==null)   //很有可能这个节点数据为null,但是对于数据不是null的节点,比较用的是equals,所以需要分开判断
        {
            for (Node tmp = head; tmp != null; tmp = tmp.next)
            {
                if(tmp.data==null)  //找到该节点
                {
                    if(Unlink(tmp))  //删除该节点
                        return true;
                }
            }
            return false;
        }
        else {
            for (Node tmp = head; tmp != null; tmp = tmp.next) {
                if (data.equals(tmp.data)) {
                    if (Unlink(tmp))
                        return true;
                }
            }
            return false;
        }
    }
    public Object set(int index, Object newdata)  //替换数据
    {
        if(isIndex(index))  //首先下标是合法的
        {
            Node tmp=getNode(index);
            Object olddata=tmp.data;
            tmp.data=newdata;
            return olddata;
        }
        return null;
    }
    public int contains(Object data)
    {
        if(data==null)
        {
            int i=0;
            for(Node tmp=head;tmp!=null;tmp=tmp.next) {
                if (tmp.data == null)
                    return i;
                else
                    i++;
            }
        }
        else
        {
            int i=0;
            for(Node tmp=head;tmp!=null;tmp=tmp.next)
            {
                if(data.equals(tmp.data))
                    return i;
                else
                    i++;
            }
        }
        return -1;
    }
    private boolean Unlink(Node node)//删除node结点
    {
        //既然要删除一个结点,是将prev和next链接在一起,那么对prev 是否为空进行操作,next是否为空进行操作
        Node prev=node.prev;
        Node next=node.next;
        if(prev==null)
        {
            this.head=next;
            //head.prev=null;  //不能有该语句,如果next为空
        }
        else
        {
            prev.next=next;
            node.prev=null;  //相当于清除该节点的prev
        }
        if(next==null)  //删除尾结点  如果删除的仅有结点,即既是头结点也是为节点,会走这一句
        {
            this.tail=prev;
        }
        else
        {
            next.prev=prev;
            node.next=null;  //相当于清除该节点的next
        }
        node.data=null; //将该节点数据置空
        this.size--;
        return true;
    }
    public  Object get(int index)  //返回索引为index的数据
    {
        if(isIndex(index))
        {
            Node tmp=getNode(index);
            return tmp.data;
        }
        System.out.println("下标不合法");
        return null;
    }
    public void printLink()  //遍历链表
    {
        for(Node tmp=head;tmp!=null;tmp=tmp.next)
        {
            System.out.println(tmp.data);
        }


    }
    public void clear()  //销毁链表
    {
        for(Node tmp=head;tmp!=null;)
        {
            Node next=tmp.next;
            tmp.next=null;
            tmp.prev=null;
            tmp.data=null;
            tmp=null;
            tmp=next;
            size--;
        }
        head=tail=null;
    }
    public int size()
    {
        return size;
    }
    public Object[] toArray()  //将链表转为数组
    {
        if(size!=0)
        {
            Object[] linkArray=new Object[this.size];
            int index=0;
            for(Node tmp=head;tmp!=null;tmp=tmp.next)
            {
                linkArray[index]=tmp.data;
                index++;
            }
            return linkArray;
        }

        return null;
    }
    private boolean isIndex(int index)  //判断下标是否合法
    {
        return index>=0 && index<size;
    }
    private Node getNode(int index)  //返回下标所在的结点
    {
        if(index<size/2)  //元素的一半,从head向尾找
        {
            Node start=head;
            for(int i=0;i<index;i++)
            {
                start=start.next;
            }
            return start;
        }
        else
        {
            Node end=tail;
            for(int i=size-1;i>index;i--)
            {
                end=end.prev;
            }
            return end;
        }
    }
}
class factory   //一个工厂专门生产对象,这样在客户端就不用new对象
{
    public static LinkImpl getLink()
    {
        return new LinkImpl();
    }
}
public class DoubleLink
{
    public static void main(String[] args)
    {
        Ilink l=factory.getLink();
        l.add("pick");
        l.add("hello");
        l.add(null);
        System.out.println(l.set(2,19));
        l.printLink();
        System.out.println("*************"+l.size());
        l.remove("pick");
        l.remove(null);
        l.printLink();
        System.out.println(l.get(1));
        System.out.println("*************");
        l.clear();
        l.printLink();
        System.out.println(l.size());
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sophia__yu/article/details/83657550