鏈表

鏈表

接口

public interface LinkedList<E>{
    void addFirst(E e);
    void add(int index,E e);
    void removeFirst();
    void remove(int index);
    void remove(E e);
    boolean contains(E e);
    E get(int index);
    void set(int index,E e);
    boolean isEmpty();
    Object[] toArray();

}

在這裏插入圖片描述
在這裏插入圖片描述

單向鏈表

public class SingleLinkedList<E> implements LinkedList<E> {
    private class Node{
        E e;
        Node next;

        public Node(E e) {
            this.e = e;
        }

        public Node(E e, Node next) {
            this.e = e;
            this.next = next;
        }
    }
    private Node dummyHead;
    private int size;
    public SingleLinkedList(){
              dummyHead=new Node(null,null);
    }
    @Override
    public void addFirst(E e) {
        add(0,e);
    }

    @Override
    public void add(int index, E e) {
        //判斷下標是否越界,由於插入的位置可以是尾結點的後面,所以index可以爲size
        if(index<0||index>size){
            throw new IndexOutOfBoundsException("下標越界");
        }
        //獲取前驅結點
        Node prev=prev(index);
        //將結點插入
        prev.next=new Node(e,prev.next);
        size++;

    }
    private Node prev(int index){
        //要找到一個節點的前驅結點,就要從頭結點的前驅結點開始找起。
        Node temp=dummyHead;
        for(int i=0;i<index;i++){
            temp=temp.next;
        }
        return temp;
    }
		
    //刪除頭結點
    @Override
    public void removeFirst() {
        remove(0);

    }

    @Override
    public void remove(int index) {
        checkIndex(index);
        Node prev=prev(index);
        Node curr=curr(index);
        prev.next=curr.next;
        curr=curr.next=null;
        size--;
    }
    private Node curr(int index){
        Node temp=dummyHead.next;
        for(int i=0;i<index;i++){
            temp=temp.next;
        }
        return temp;
    }

    @Override
    public void remove(E e) {
        Node prev=dummyHead;
        Node curr=dummyHead.next;
        while(curr!=null){
            if(curr.e.equals(e)){
                //找到和當前節點值相同的結點,將結點刪除
                 prev.next=curr.next;
                 curr=curr.next=null;
            }
            curr=curr.next;
            prev=prev.next;
        }
    }

    @Override
    public boolean contains(E e) {
        for (Node node=dummyHead.next;node!=null;node=node.next){
            if(node.e.equals(e)){
                return true;
            }
        }
        return false;
    }

    @Override
    public E get(int index) {
        checkIndex(index);
        return curr(index).e;
    }

    @Override
    public void set(int index, E e) {
        checkIndex(index);
        Node curr=curr(index);
        curr.e=e;
    }

    @Override
    public boolean isEmpty() {
        return size==0;
    }

    @Override
    public Object[] toArray() {
        Object[] element=new Object[size];
        int i=0;
        for(Node node=dummyHead.next;node!=null;node= node.next){
            element[i++]=node.e;

        }
        return element;
    }
        private void checkIndex(int index){
        if(index<0||index>=size){
            throw new IndexOutOfBoundsException("下標越界");
        }
    }
}

在這裏插入圖片描述

[外鏈圖片轉存失敗(img-OeYbTJXq-1562382964503)(E:\javaSE_knowledgepoint\鏈表\鏈表_04.png)]

[外鏈圖片轉存失敗(img-lOA1VHnp-1562382964509)(E:\javaSE_knowledgepoint\鏈表\鏈表_05.png)]

雙向鏈表

public class DoubleLinkedList<E> implements LinkedList<E> {
    private class Node{
        E e;
        Node prev;
        Node next;

        public Node(E e) {
            this.e = e;
        }
    }
    private Node head;
    private Node tail;
    private int size;

    @Override
    public void addFirst(E e) {
        add(0,e);
    }

    @Override
    public void add(int index, E e) {
        if(index<0||index>size){
            throw new IndexOutOfBoundsException("下標越界");
        }
        
        Node curr = null;
        if(index==size) {
            //說明要插入位置當前沒有結點
            curr = null;
        }else {
            //在curr()方法中尋找結點
            curr=curr(index);
        }
        //創建新節點
        Node node=new Node(e);
        if(curr==null){
            //當前量表長度爲0,說明當前鏈表沒有結點
            if(size==0){
                head=tail=new Node(e);
            }else{
                //當前要插入的結點要作爲鏈表的尾結點
                tail.next=node;
                node.prev=tail;
                tail=node;
            }
        }else{
            //找到當前節點覺得前驅結點
            Node prev=curr.prev;
            //如果當前節點爲空,頭插
            if(curr==head){
                node.next=head;
                head.prev=node;
                head=node;
            }else{
                node.next=prev.next;
                prev.next=node;
                node.prev=curr.prev;
                curr.prev=node;
            }
        }
        size++;
    }
    private Node curr(int index){
        //由於是雙向鏈表,所以從頭結點和尾結點都可以訪問鏈表,所以可以判斷要找的index裏頭結點近還是尾結點近從而減少訪問次數
        int t=size>>1;
        if(index<t) {
            Node temp = head;
            for (int i = 0; i < index; i++) {
                temp = temp.next;
            }
            return temp;
        }else{
            Node temp=tail;
            for (int j=size-1;j>index;j--){
                temp=temp.prev;
            }
            return temp;
        }
    }

    @Override
    public void removeFirst() {
        remove(0);
    }

    @Override
    public void remove(int index) {
       checkIndex(index);
        Node curr=curr(index);
        Node prev=curr.prev;
        Node next=curr.next;
        if(curr==head){
            //當前節點石頭結點,將頭結點向後移
            head=head.next;
            head.prev=null;
        }else {
            //當前節點不是頭結點
            prev.next=curr.next;
            curr.next=null;
        }
        if(curr==tail){
            //當前節點是尾結點
            tail=tail.prev;
            tail.next=null;
        }else {
            next.prev=curr.prev;
            curr.prev=null;
        }
        curr=curr.next=curr.prev=null;
        size--;
    }
    private void checkIndex(int index){
        if(index<0||index>=size){
            throw new IndexOutOfBoundsException("下標越界");
        }
    }

    @Override
    public void removeNode(E e) {
        //刪除所有值爲e的結點
        Node first=head;
        int index=0;
        //當前節點不爲空
        while(first!=null){
            //將temp存入first的下一個結點
            Node temp=first.next;
            if(first.e.equals(e)){
                //找到相同的結點通過索引的方式刪除,同時index不加1
                remove(index);

            }else {
                //否則index向後走一步
                index++;

            } 
            first=temp;
        }
    }

    @Override
    public boolean contains(E e) {
        for (Node temp=head;temp!=null;temp=temp.next){
            if(temp.e.equals(e)){
                return true;
            }
        }
        return false;
    }

    @Override
    public E get(int index) {
        checkIndex(index);
        return curr(index).e;
    }

    @Override
    public void set(int index, E e) {
        checkIndex(index);
        Node curr=curr(index);
        curr.e=e;
    }

    @Override
    public boolean isEmpty() {
        return size==0;
    }

    @Override
    public Object[] toArray() {
        Object[] element=new Object[size];
        int i=0;
        for(Node node =head; node!=null; node= node.next){
            element[i++]=node.e;

        }
        return element;
    }
}

;
}

@Override
public boolean isEmpty() {
    return size==0;
}

@Override
public Object[] toArray() {
    Object[] element=new Object[size];
    int i=0;
    for(Node node =head; node!=null; node= node.next){
        element[i++]=node.e;

    }
    return element;
}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章