1. 程式人生 > >Java實現雙鏈表的具體實現加註釋

Java實現雙鏈表的具體實現加註釋

雙向迴圈連結串列的節點裡麵包含前指標prev,指向下一個節點的指標next,和節點內容data。因為指向讓使用者去操作最外邊的測試程式,所以使用者不用知道有節點的存在,因此把節點設定為內部類。

首先用一個介面區羅列要實現的功能,主要包括增加節點,刪除節點,判斷該節點是否存在,判斷連結串列的大小,判斷連結串列是否為空,獲取連結串列的內容等

interface ILink{//定義介面
    /**
     *  插入節點,
     * @param obj Object可以接收一切物件
     */
    void add(Object obj);
    /**
     *  //刪除節點,用布林值返回是否刪除成功,
     * @param obj 要刪除的節點
     * @return  1成功,0失敗、
     */
    boolean remove(Object obj);

    /**
     * 修改指定位置的內容
     * @param index 指定位置
     * @param newData 新節點的內容
     * @return 返回之前節點的內容
     */
    Object set(int index,Object newData);

    /**
     * 獲取指定節點的內容
     * @param index  指定節點
     * @return 節點內容
     */
    Object get(int index);

    /**
     * 判斷連結串列中是否穿在該節點
     * @param data 節點內容
     * @return  返回-表示不存在該節點
     */
    int contains(Object data);

    /**
     * 求連結串列的大小
     * @return 返回連結串列的長度
     */
    int size();

    /**
     * 清空連結串列
     */
    void clear();

    /**
     * 將連結串列轉化為陣列
     * @return 返回節點內容陣列
     */
    Object[] toArray();

    /**
     * 列印連結串列
     */
    void print();
}

定義一個類去實現接口裡面的具體功能。各個函式的具體實現以及實現原理都在程式碼後邊備註了。

class LinkImpl implements ILink{//定義一個類 ,繼承介面,並實現它
    private Node head;
    private Node last;
    private int size;
    private class Node{//定義節點對外部不可見
        private Node prev;
        private Node next;
        private Object data;
        public Node(Node prev,Node next,Object data){
            this.prev=prev;
            this.next=next;
            this.data=data;
        }
    }
    @Override
    public void add(Object obj){
        Node temp=this.last;//讓temp指向最後一個節點
        //讓新節點的prev指向最後一個節點,讓next指標為null,把新增的節點內容obj給data
        Node newNode=new Node(temp,null,obj);
        this.last=newNode;//讓最後一個指標指向newNode

        if(this.head==null){//判斷頭結點是否為空
            this.head=newNode;//為空,頭結點節等於新節點
        }else{//不為空,temp的下一個節點等於新節點
            temp.next=newNode;
        }
        this.size++;//連結串列的大小加一
    }

    @Override
    public boolean remove(Object obj) {
        if(obj==null){//如果輸出物件為空
            for(Node temp=head;temp!=null;temp=temp.next){
                if(temp.data==null){//找到內容為空的物件
                    unLink(temp);//刪除物件
                    return true;
                }
            }
        }else{//刪除內容不為空
            for(Node temp=head;temp!=null;temp=temp.next){
                if(obj.equals(temp.data)){//判斷刪除內容個和連結串列內容是否一致
                    unLink(temp);//刪除物件
                    return true;//刪除成功
                }
            }
        }
        return false;//刪除失敗
    }

    @Override
    public Object set(int index, Object newData) {
        if(!isLinkIndex(index)){//判斷節點是否存在,不存在返回null
            return null;
        }
        Object element=node(index).data;//獲取該節點的內容
        node(index).data=newData;//更改 節點的內容
        return element;//返回更改前的節點
    }

    @Override
    public Object get(int index) {
        if(!isLinkIndex(index)){//判斷節點是否存在,不存在返回null
            return null;
        }
        return node(index).data;//節點存在返回他的內容
    }

    @Override
    public int contains(Object data) {
        int i=0;
        if(data==null){//當data等於空時,直接遍歷一遍看看裡面有沒有data==null
            for(Node temp=head;temp!=null;temp=temp.next){
                if(temp.data==null){//找到temp.data等於null是返回i
                    return i;
                }
                i++;//繼續向後尋找
            }
        }else{//data不等於空時
            for(Node temp=head;temp!=null;temp=temp.next){
                if(data.equals(temp.data)){//用equals方法判斷內容是否相等
                    return i;//相等返回i
                }
                i++;
            }
        }
        return -1;//不存在返回-1
    }

    @Override
    public int size() {
        return this.size;//this表示呼叫當前物件
    }

    @Override
    public void clear() {
        for(Node temp=head;temp!=null;){
            Node flag=temp.next;//提前儲存下一個節點
            temp.prev=temp=temp.next=null;//讓節點的三個部分都為null
            temp=flag;//讓temp等於下一個節點
            this.size--;//清空一個節點連結串列的大小減一

        }
    }

    @Override
    public Object[] toArray() {
        Object[] result=new Object[size];//定義一個物件陣列
        int i=0;
        for(Node temp=head;temp!=null;temp=temp.next){
            //定義一個temp等於頭節點,區便利連結串列
            result[i++]=temp.data;//把temp的值給物件陣列
        }
        return result;//返回物件陣列
    }

    @Override
    public void print() {
        Object[] data =this.toArray();
        for(Object temp:data){//foreach迴圈輸出內容
            System.out.println(temp);
        }
    }
    private boolean isLinkIndex(int index){
        //判斷這個節點是否在這個連結串列裡
        return index>=0&&index<size;
    }
    private Node node(int index){//在連結串列中找這個節點,並返回該節點
        if(index<(size>>1)){//判斷這個節點是否在前半部分
            Node temp=head;
            for(int i=0;i<index;i++){
                temp=temp.next;//向後迴圈直到等於index
            }
            return temp;
        }
        Node temp=this.last;//節點在後半部分
        for(int i=size-1;i>index;i--){//節點從最後一個向前數,到index時停止
            temp=temp.prev;//向前迴圈直到等於index
        }
        return temp;
    }
private void unLink(Node node){//刪除節點
        Node prev =node.prev;
        Node next=node.next;
        if(prev==null){//刪除頭結點
            this.head=next;//讓head等於next
        }else{
            prev.next=next;//讓前一個指標的next指向下一個節點
            node.prev=null;//讓前節點的prev=null
        }
        if(next==null){//刪除尾節點
            this.last=prev;//讓他的尾節點等於他前一個節點
        }else{
            next.prev=prev;//next的前指標prev等於前一個節點
            node.next=null;//讓node 的下一個節點為空
        }
        node.data=null;//把節點的內容置空
        this.size--;//連結串列的大小減一
}
}

測試函式

public class Link {
    public static void main(String[] agrs){

        ILink link = new LinkImpl();
        link.add("火車頭");
        link.add("車廂1");
        link.add("車廂2");
        link.add(null);
        link.add("車廂尾");
        link.print();
        System.out.println();
        link.remove("火車頭");
        link.print();
        System.out.println();

        link.remove("車廂尾");
        link.print();
        System.out.println();

        link.remove(null);
        link.remove("哈哈哈");
        link.print();
    }
}