數據結構-線性表-模擬實現順序表ArrayList

模擬實現順序表ArrayList

1、定義接口

不管是順序表仍是鏈表,它們都是線性表,都須要進行增刪改查操做。
因此首先,定義一個線性表接口List,包含線性表的操做數組

/**
 * 線性表接口
 * 和存儲結構無關(順序表,鏈表)
 */
public interface List
{
    //返回線性表的大小,即元素的個數
    public int size();

    //返回線性表中序號爲i 的數據元素
    public Object get(int i);

    //若是線性表爲空,返回true,不然返回false
    public boolean isEmpty();

    //判斷線性表中是否包含數據元素e
    public boolean contains(Object e);

    //返回數據元素e 在線性表中的序號
    public int indexOf(Object e);

    //將數據元素e 插入到線性表中i 號位置
    public void add(int i, Object e);

    //將數據元素e 插入到線性表末尾
    public void add(Object e);

    //將數據元素e 插入到元素obj 以前
    public boolean addBefore(Object obj, Object e);

    //將數據元素e 插入到元素obj 以後
    public boolean addAfter(Object obj, Object e);

    //刪除線性表中序號爲i 的元素,並返回之
    public Object remove(int i);

    //刪除線性表中第一個與e 相同的元素
    public boolean remove(Object e);

    //替換線性表中序號爲i 的數據元素爲e, 返回原數據元素
    public Object replace(int i, Object e);
}

2、建立順序表類ArrayList並實現接口List

一、順序表底層採用的是數組,長度能夠動態變化

private Object[] elementData; //底層是一個數組,目前尚未肯定長度
    private int size; //不是數組分配了幾個空間,而是數組中元素的個數

二、編寫構造方法指定數組初始長度

public ArrayList(int initalCapacity) {
        //給數組分配指定數量的空間
        elementData = new Object[initalCapacity];
        //指定順序表的元素個數,默認是0
//        size = 0;
    }
public ArrayList() {
        //沒有指定長度,默認長度是4
        this(4);
    }

以上代碼寫完,就能夠建立順序表了,可是裏面的操做方法尚未實現安全

三、實現add方法,將數據元素e 插入到線性表中i 號位置,代碼以下

public void add(int i, Object e) {
        //i 的位置要正確
        if (i<0 || i > size){
            throw new MyArrayIndexOutOfBoundsException("數組索引越界異常:"+i);
        }
        //數組元素個數等於數組長度時,須要擴容
        if(size == elementData.length){
            //擴容方法
            grow();
        }
        //後移i 及其後面的元素,從最後一個元素開始
        for (int j = size; j > i ; j--) {
            elementData[j] = elementData[j-1];
        }
        //給數組第i 個位置賦值
        elementData[i] = e;
        //數組元素個數+1
        size++;
    }

首先判斷索引是否正確,不正確就拋出一個自定義異常app

public class MyArrayIndexOutOfBoundsException extends RuntimeException {
    public MyArrayIndexOutOfBoundsException() {
    }

    public MyArrayIndexOutOfBoundsException(String message) {
        super(message);
    }
}

而後當數組元素個數等於數組長度時,調用grow()方法進行擴容,grow()方法有兩種實現ui

//基本思路是這樣
    private void grow(){
        //建立一個新數組,長度是舊數組2倍
        Object[] newArr = new Object[elementData.length * 2];
        //將舊數組數據拷貝到新數組
        for (int i = 0; i < size; i++) {
            newArr[i] = elementData[i];
        }
        //讓舊數組 指向 新數組
        elementData = newArr;
    }
    
    //一步到位
    private void grow(){
        //擴容 拷貝 賦值
        elementData = Arrays.copyOf(elementData, elementData.length * 2);
    }

最後實現添加操做:須要從數組尾部元素開始,將第i 位及其以後的元素向後移一位,而後把e 賦值給第i 個位置的元素,最後數組元素個數+1this

四、把元素添加到線性表末尾,是add()方法的特殊狀況

public void add(Object e) {
        this.add(size, e);
    }

五、get()方法,返回線性表中序號爲i 的元素,即數組中下標爲i 的元素

public Object get(int i) {
        if (i < 0 || i >= size) {//i < 0 或者 i >= size
            throw new MyArrayIndexOutOfBoundsException("數組索引越界異常:" + i);
        }
        return elementData[i];
    }

判斷索引是否正確,錯誤拋出自定義異常線程

六、remove(int i)方法,刪除線性表中序號爲i 的元素,並返回之

public Object remove(int i) {
        if (i < 0 || i >= size) {
            throw new MyArrayIndexOutOfBoundsException("數組越界異常:"+ i);
        }
        Object empt = elementData[i];
        for (int j = i; j < size; j++) {
            elementData[j] = elementData[j+1];
        }
        elementData[size-1] = null;
        size--;
        return empt;
    }

3、重寫toString()方法

public String toString() {
        if (size == 0){
            return "[]";
        }
        StringBuilder builder = new StringBuilder("[");
        for (int i = 0; i < size; i++) {
            if (i != size - 1){
                builder.append(elementData[i]+",");
            }else {
                builder.append(elementData[i]);
            }
        }
        builder.append("]");
        return builder.toString();
    }

擴展

StringBuffer和StringBuilder很是相似,均表明可變的字符序列。 這兩個類都是抽象類AbstractStringBuilder的子類,方法幾乎如出一轍。
StringBuffer 線程安全,作線程同步檢查, 效率較低。
StringBuilder 線程不安全,不作線程同步檢查,所以效率較高。 建議使用該類。code

4、核心

數組擴容、元素前移、後移索引

ArrayList源碼中擴容爲50%接口

int newCapacity = oldCapacity + (oldCapacity >> 1);
相關文章
相關標籤/搜索