01-java實現動態數組


01-手擼動態數組

本篇是戀上數據結構第一季個人總結
借鑒https://juejin.im/post/6844904001478066183#heading-0
本人git https://github.com/bigeyes-debug/Algorithm

一丶 數組

數組是一種順序存儲的線性表,所有元素的內存地址是連續
由於數組的內存連續性,數組默認情況下(指靜態數組)是不會動態擴容的,而我們常常希望是數組是可以動態擴容的.

二丶動態數組的設計

2.1動態數組的屬性

  • size是動態數組的大小,我們設置這個屬性,可以通過返回動態數組的大小,獲取當前動態數組元素的個數
  • elements 存儲數據的數組(使用靜態數組保存,動態擴充代碼后面會提到)
  • DEFAULT_CAPACITY 指定默認的動態數組的默認數組大小
  • ELEMENT_NOT_FOUND 遍歷循環查找元素的時候,如果找不到元素,就返回-1
    private int size;
    private E[] elements;
    private static final int DEFAULT_CAPACITY=10;
    private static final int ELEMENT_NOT_FOUND=-1;

2.2 動態數組的接口

// 元素的數量
int size(); 
// 是否為空
boolean isEmpty();
// 是否包含某個元素
boolean contains(E element); 
// 添加元素到最后面
void add(E element); 
// 返回index位置對應的元素
E get(int index); 
// 設置index位置的元素
E set(int index, E element); 
// 往index位置添加元素
void add(int index, E element); 
// 刪除index位置對應的元素 
E remove(int index); 
// 查看元素的位置
int indexOf(E element); 
// 清除所有元素
void clear(); 

根據屬性和接口,我們可以直接實現一些接口的方法.

三丶動態數組的實現

3.1 數組的數量

size就是數組中元素的數量,調用size方法,直接返回數組中元素的數量

    public int size() {
        return size;
    }

3.2 數組是否為空

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

3.3 添加元素

添加元素實現兩個接口

  • public void add(E element) 只添加元素

  • public void add(int index,E element) 指定添加元素的位置)

代碼如下:

public void add(int index, E element) {
    elements[index] = element;
    size++;
}
public void add(E element) {
        add(size,element);
    }

但添加元素存在兩種情況
第一種情況:在最后一個元素的后面添加新元素
第二種情況:將元素插入到某個位置(非最后面
第一種情況不需要處理,第二種情況我們需要插入數據的位置后面的元素逐個向前移
特別需要注意的是一定要從后往前移,如果從前往后,后面的元素會被覆蓋

考慮第二種情況之后,我們的add方法代碼如下

    public void add(int index,E element) {
        for(int i=size;i>index;i--) {
            elements[i]=elements[i-1];
        }
        elements[index]=element;
        size++;
    }

3.3.1數組越界

如果add的index的值大於size,程序就會異常,index也應該大於,所以我們在此之前要加個判斷

    private void rangeCheckForAdd(int index) {
        if(index<0||index>size) {
           outOfBounds(index);
        }
    public void add(int index,E element) {
       rngeCheckForAdd(index);
        for(int i=size;i>index;i--) {
            elements[i]=elements[i-1];
        }
        elements[index]=element;
        size++;
    }

3.3.2數組擴容

  • 由於數組elements最大的容量只有10,所以當數組存滿元素時,就需要對數組進行擴容。

  • 因為數組是無法動態擴容的,所以需要創建一個新的數組,這個數組的容量要比之前數組的容量大。

  • 然后在將原數組中的元素存放到新數組中,這樣就實現了數組的擴容。

private void ensureCapacity() {
    // 獲取數組當前容量
    int oldCapacity = elements.length;
    // 如果 當前存儲的元素個數 < 當前數組容量, 直接返回
    if (size < oldCapacity) return;
    // 新數組的容量為原數組容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 創建新數組
    E[] newElements = (E[]) new Object[newCapacity];
    // 原數組中的元素存儲到新數組中
    for (int i = 0; i < size; i++) {
    	newElements[i] = elements[i];
    }
    // 引用新數組
    elements = newElements;
}
     

   public void add(int index,E element) {
   // index應該0<index<size
        rangeCheckForAdd(index);
        // 動態擴容
         ensureCapacity(size+1);
         //數組元素前移
        for(int i=size;i>index;i--) {
            elements[i]=elements[i-1];
        }
        //插入元素
        elements[index]=element;
        //數組數量+1
        size++;
    }

3.4 清空元素

在java中,當對象沒有指針指向時,就會自動被回收,所以我們只需要將數組的指向元素的指針設置為null,就可以了.

    public void clear() {
        for(int i=0;i<size;i++) {
            elements[i]=null;
        }
       size=0;
    }

3.5刪除元素

刪除元素的只需要將后面的元素往前移就可以,這里需要注意的是0<=index<size

    private void  outOfBounds(int index) {
        throw new IndexOutOfBoundsException("Index:"+index+",Size:" + size);
    }
    private void rangeCheck(int index) {
        if(index<0||index>=size) {
            outOfBounds(index);
        }
    }
    public E remove(int index) {
        rangeCheck(index);
        E old=elements[index];
        //后面的元素前移
        for(int i=index+1;i<size;i++) {
            elements[i-1]=elements[i];
        }
        //一定要先減再清空
        elements[--size]=null;
        return old;
    }

為什么要--size?
數組有5個元素.size為5,而第五個元素的下標是4
所有需要先--然后再設置為null

3.5修改元素

只需找到指定下標,替換就可,同樣要注意越界

public E set(int index,E element) {
        rangeCheck(index);
        E old = elements[index];
        elements[index]=element;
        return old;
    }

3.6查找元素

查詢元素,只需要將指定索引的元素返回,注意索引是否越界即可。

public E get(int index) {
    rangeCheck(index);
    return elements[index];
}

3.7 查找元素位置

查找元素存在兩種情況,
第一種情況,要查找的元素為null,
第二種情況,要查找的元素不為null
null.equals回報空指針異常
我們分開進行處理,for循環遍歷即可

    public int indexOf(E element) {
        if(element == null) {
            for(int i=0;i<size;i++) {
                if(elements[i]==null) {
                    return i;
                }
            }
        }
        else {
            for(int i=0;i<size;i++) {
                if(element.equals(elements[i])) {
                    return i;
                }
            }
        }  
        return ELEMENT_NOT_FOUND;

    }

3.8 是否包含元素

    public boolean contains(E element) {
        return indexOf(element)!=ELEMENT_NOT_FOUND;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM