Java數據結構算法

目錄node

 
  

 

 

鏈表

  「數組」做爲數據存儲結構有必定的缺陷數組

  • 無序數組——搜索效率是低效的
  • 有序數組——插入效率低

  無論在哪一種數組中刪除效率都很低,建立數組後,大小不可改變數據結構

線性數據結構

  

     

爲何鏈表很重要?

  • 最簡單的動態數據結構
  • 更深刻的理解引用(或者指針)
  • 更深刻的理解遞歸
  • 輔助組成其餘的數據結構(圖結構、哈希表、隊列)

鏈表 LinkedListapp

  數據儲存在「節點(Node)」中,一個鏈節點是某個類的對象ide

  

  

  優勢:真正的動態,不須要處理固定容量的問題(不用像數組new出來一片空間)this

  缺點:不能隨機訪問(數組開闢的空間在內存上是連續的,能夠經過下標計算出內存地址進行隨機訪問,而鏈表必須是順序訪問,因爲依靠next一層一層鏈接,在計算機的底層,每個節點對應的內存地址不一樣spa

數組和鏈表的對比

  數組:最好用於索引有語意的狀況(user[1])3d

  優勢:快速查詢指針

  數組:最好不用於索引有語意的狀況code

  鏈表:動態


應用

一、在鏈表頭添加元素

  在數組中,在最後面添加元素是最方便的,由於有size在跟蹤數組的最後一個元素

  可是鏈表偏偏相反,鏈表頭添加元素,由於有head頭結點,沒有跟蹤最後一個元素的結點

  

public class LinkedList<E>{

    private class Node{
        public E e;
        public Node next;

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

        public Node(E e){
            this(e,null);
        }

        public Node(){
            this(null,null);
        }
    }

    private Node head;
    private int size;

    public LinkedList(){
        head=null;
        size=0;
    }

    //獲取鏈表中元素個數

    public int getSize() {
        return size;
    }

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

    //在鏈表頭結點添加元素
    public  void addFirst(E e){
        Node node=new Node(e);
        node.next=head;
        head=node;

        //head=new Node(e);至關於上面三行
        size++;
    }
}
View Code

 

二、在鏈表中間(末尾)添加元素

   在搜索爲2的位置插入元素

  

   關鍵:找到添加結點的前一個節點

  注意:如插入到索引爲0的節點後面,頭結點沒有前驅節點

  //在鏈表中間添加元素
    public void add(int index,E e){
        //判斷索引的和發現
        if(index<0||index>size){
            throw new IllegalArgumentException("add failed,illegal index");
        }
        //若是在鏈表頭添加,因爲鏈表頭沒有前驅節點,需特殊處理
        if(index==0){
            addFirst(e);
        }else{
            Node pre=head;
            for (int i = 0; i <index-1 ; i++) {
                //一直將前驅節點向前移,直到找到index位置的節點
                pre=pre.next;
                Node node=new Node(e);
                node.next=pre.next;
                pre.next=node;

                //pre.next=new Node(e,pre.next);至關於上面三行
                size++;
            }
        }
    }

    //在鏈表末尾添加元素
    public void addLast(E e){
        add(size,e);
    }
View Code

 三、爲鏈表設置虛擬頭結點

  因爲頭結點沒有前驅節點,在鏈表頭結點和其餘位置插入元素,會有所不一樣

  所以構建一個虛擬頭結點爲null,就不須要對頭結點進行特殊處理,只須要找到待添加元素的前一個節點

  

    //在鏈表中間添加元素
    public void add(int index,E e){
        //判斷索引的和發現
        if(index<0||index>size){
            throw new IllegalArgumentException("add failed,illegal index");
        }
        //若是在鏈表頭添加,因爲鏈表頭沒有前驅節點,需特殊處理
            Node pre=dummyHead;
            for (int i = 0; i <index; i++) {
                //一直將前驅節點向前移,直到找到index位置的節點
                pre=pre.next;
                Node node=new Node(e);
                node.next=pre.next;
                pre.next=node;

                //pre.next=new Node(e,pre.next);至關於上面三行
                size++;
            }
    }

    //在鏈表末尾添加元素
    public void addLast(E e){
        add(size,e);
    }

    //在鏈表頭結點添加元素
    public void addFirst(E e){
        add(0,e);
    }
View Code

 四、鏈表

 

    //得到鏈表的第index(0-base)個位置的元素
    public E get(int index){
        //判斷索引的合法性
        if(index<0||index>size){
            throw new IllegalArgumentException("add failed,illegal index");
        }
        Node cur=dummyHead.next;
        for (int i = 0; i <index ; i++) {
            cur=cur.next;
        }
        return cur.e;
    }

    //獲取鏈表第一個元素
    public E getFirst(){
        return get(0);
    }

    public E getLast(){
        return get(size-1);
    }
View Code
相關文章
相關標籤/搜索