1. 程式人生 > >[數據結構] - 數組

[數據結構] - 數組

throw 長度 空間 class a 否則 組類型 解決 exc index索引

1、Java數組介紹

  在Java中,數組是用來存放同一種數據類型的集合,註意只能存放同一種數據類型(Object類型數組除外)。

  • 在內存中,數組是一塊連續的區域。 拿上面的看電影來說,這幾個人在電影院必須坐在一起。

  • 數組需要預留空間,在使用前要先申請占內存的大小,可能會浪費內存空間。 比如看電影時,為了保證10個人能坐在一起,必須提前訂好10個連續的位置。這樣的好處就是能保證10個人可以在一起。但是這樣的缺點是,如果來的人不夠10個,那麽剩下的位置就浪費了。如果臨時有多來了個人,那麽10個就不夠用了,這時可能需要將第11個位置上的人挪走,或者是他們11個人重新去找一個11連坐的位置,效率都很低。如果沒有找到符合要求的作為,那麽就沒法坐了。
  • 插入數據和刪除數據效率低,插入數據時,這個位置後面的數據在內存中都要向後移。刪除數據時,這個數據後面的數據都要往前移動。 比如原來去了5個人,然後後來又去了一個人要坐在第三個位置上,那麽第三個到第五個都要往後移動一個位子,將第三個位置留給新來的人。 當這個人走了的時候,因為他們要連在一起的,所以他後面幾個人要往前移動一個位置,把這個空位補上。
  • 隨機讀取效率很高。因為數組是連續的,知道每一個數據的內存地址,可以直接找到給地址的數據。
  • 並且不利於擴展,數組定義的空間不夠時要重新定義數組。一種解決辦法是封裝一次數組,數組元素超過75%時候就動態擴容,新申請一個1.5倍的數組,把原來的數組全部拷貝過去。

①、數組的聲明

第一種方式:

數據類型 []  數組名稱 = new 數據類型[數組長度];

這裏 [] 可以放在數組名稱的前面,也可以放在數組名稱的後面,我們推薦放在數組名稱的前面,這樣看上去 數據類型 [] 表示的很明顯是一個數組類型,而放在數組名稱後面,則不是那麽直觀。

第二種方式:

數據類型 [] 數組名稱 = {數組元素1,數組元素2,......}

 這種方式聲明數組的同時直接給定了數組的元素,數組的大小由給定的數組元素個數決定。

//聲明數組1,聲明一個長度為3,只能存放int類型的數據
int [] myArray = new int[3];
//聲明數組2,聲明一個數組元素為 1,2,3的int類型數組
int [] myArray2 = {1,2,3};

②、訪問數組元素以及給數組元素賦值

  數組是存在下標索引的,通過下標可以獲取指定位置的元素,數組小標是從0開始的,也就是說下標0對應的就是數組中第1個元素,可以很方便的對數組中的元素進行存取操作。

  前面數組的聲明第二種方式,我們在聲明數組的同時,也進行了初始化賦值。
  
 

//聲明數組,聲明一個長度為3,只能存放int類型的數據
int [] myArray = new int[3];
//給myArray第一個元素賦值1
myArray[0] = 1;
//訪問myArray的第一個元素
System.out.println(myArray[0]);

上面的myArray 數組,我們只能賦值三個元素,也就是下標從0到2,如果你訪問 myArray[3] ,那麽會報數組下標越界異常。

③、數組遍歷

  數組有個 length 屬性,是記錄數組的長度的,我們可以利用length屬性來遍歷數組。
  

//聲明數組2,聲明一個數組元素為 1,2,3的int類型數組
int [] myArray2 = {1,2,3};
for(int i = 0 ; i < myArray2.length ; i++){
    System.out.println(myArray2[i]);
}

2、簡單封裝一個動態數組

package me.liangtian.array;
 
public class Array<E> {
    /**
     * 存放數據的數組
     */
    private E[] data;
    /**
     * 數組中現有數據量
     */
    private int size;
    
    public Array(int capacity) {
        data = (E[])new Object[capacity];
        size = 0;
    }
    /**
     * 默認數組長度10
     */
    public Array() {
        new Array<>(10);
    }
    /**
     * 得到數組長度
     */
    public int getCapacity() {
        return data.length;
    }
    /**
     * 已有數組大小
     */
    public int getSize() {
        return size;
    }
    /**
     * 判斷數組是否為空
     */
    public boolean isEmpty() {
        return size == 0;
    }
    /**
     * 索引index處添加一個元素
     * 1.判斷索引是否有效
     * 2.判斷數組是否已經滿了,若滿了那麽擴容
     * 3.從後往前,index處的元素後移一個位置
     * 4.index索引處元素賦值
     * 5.size++
     */
    public void add(int index, E e) {
        if(index < 0 || index > size) {
            throw new IllegalArgumentException("add failed, index must between 0 and size");
        }
        if(index == size) {
            resize( 2 * data.length);
        }
        for (int i = size -1; i >= index; i--) {
            data[i+1] = data[i];
        }
        data[index] = e;
        size++;
    }
    /**
     * 在尾部添加新元素
     */
    public void addLast(E e) {
        add(size, e);
    }
    /**
     * 在頭部添加新元素
     */
    public void addFirst(E e) {
        add(0, e);
    }
    
    /**
     * 是否包含否個元素
     */
    public boolean contains(E e) {
        for (E e1 : data) {
            if(e1.equals(e)) {
                return true;
            }
        }
        return false;
    } 
    
    /**
     * 動態擴容
     * 1.新建一個容器,大小為指定大小newCapacity
     * 2.將之前的容器的元素按原有順序放到新的容器中
     * 3.將原指針指向新容器
     */
    private void resize(int newCapacity) {
        E[] newDate = (E[]) new Object[newCapacity];
        for(int i = 0; i < size; i++) {
            newDate[i] = data[i];
        }
        data = newDate;
    }
    /**
     * 查找元素E在數組中的索引
     * 1.遍歷所有的數組,若匹配到(equals非==)那麽返回索引,否則返回-1
     */
    private int find(E e) {
        for (int i = 0; i < data.length; i++) {
            if(data[i].equals(e)) {
                return i;
            }
        }
        return -1;
    }
    
    /**
     * 刪除元素並返回刪除之前的位置
     * 若不存在則返回-1
     */
    public int removeElement(E e) {
        int index = find(e);
        if(index != -1) {
            remove(index);
        }
        return index;
    }
    /**
     * 根據索引刪除元素,並返回刪除元素
     * 1.判斷索引是否有效
     * 2.將索引處的元素保存到單獨一個變量,用於返回
     * 3.將所有元素左移,索引從小到大
     * 4.將size索引處的元素清空,並且size-1
     * 5.均攤算法復雜度。為防止算法復雜度振蕩,只有size <= data.leng/4 那麽重新調整數組大小為原大小二分之一
     *   註意數組容器大小不能為0
     */
    private E remove(int index) {
        if(index < 0 || index >= size) {
            throw new IllegalArgumentException("index must between 0 and size -1");
        }
        E removeData = data[index];
        for(int i = index + 1; i < size; i++) {
            data[i-1] = data[i];
        }
        data[index] = null;
        size--;
        if(size <= data.length/4 && data.length /2 != 0) {
            resize(data.length /2);
        }
        return removeData;
    }
}

[數據結構] - 數組