1. 程式人生 > >Lava連結串列(雙向連結串列---介面實現)

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());
    }
}

在這裡插入圖片描述