歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java數據結構-線性表之順序表ArrayList

Java數據結構-線性表之順序表ArrayList

日期:2017/3/1 9:27:24   编辑:Linux編程

線性表的順序存儲結構,也稱為順序表,指用一段連續的存儲單元依次存儲線性表中的數據元素。

根據順序表的特性,我們用數組來實現順序表,下面是我通過數組實現的Java版本的順序表。

package com.phn.datestructure;
/**
 * @author 潘海南
 * @Email [email protected]
 * @TODO 順序表
 * @date 2015年7月16日
 */
public class FOArrayList<E> {
    // 順序表長度
    private int size;
    // 順序表默認數組為null
    private Object[] data = null;
    // 順序表中數組的初始化長度
    private int capacity;
    // 順序表默認初始化長度
    private static final int DEFUALT_INITIAL_SIZE = 0;
    /**
     * 默認無參構造函數
     */
    public FOArrayList() {
        this(DEFUALT_INITIAL_SIZE);
    }
    /**
     * @TODO 帶參構造函數
     * @param initialSize 初始化順序表長度
     */
    public FOArrayList(int initialSize) {
        if (initialSize < 0) {
            throw new RuntimeException("數組大小錯誤:" + initialSize);
        }
        this.data = new Object[initialSize];
        this.capacity = initialSize;
        this.setSize();
    }
    /**
     * @TODO 設置順序表的長度
     */
    private void setSize() {
        this.size = 0;
    }
    /**
     * @TODO 獲取順序表的長度
     * @return size 順序表的長度
     */
    public int size() {
        return this.size;
    }
    /**
     * @TODO 順序表添加元素
     * @param e 數據元素類型
     * @return true
     */
    public boolean add(E e) {
        ensureSize(size);
        this.data[size] = e;
        this.size++;
        return true;
    }
    /**
     * @TODO 順序表插入元素
     * @param index 插入位置
     * @param e 數據元素類型
     * @return true
     */
    public boolean insert(int index, E e) {
        if (index >= 0 && index <= size) {
            ensureSize(size);
            E temp = (E) this.data[index - 1];
            this.data[index - 1] = e;
            this.size++;
            for (int i = index; i <= size; i++) {
                E temp2 = (E) this.data[i];
                this.data[i] = temp;
                temp = temp2;
            }
        } else {
            throw new RuntimeException("數組下標錯誤:" + index);
        }
        return true;
    }
    /**
     * @TODO 順序表刪除元素
     * @param index 將要刪除的元素的索引位置
     * @return E 刪除的元素
     */
    public E remove(int index) {
        validateIndex(index);
        E e = (E) this.data[index];
        for (int i = index; i < size - 1; i++) {
            this.data[i] = this.data[i + 1];
        }
        this.size--;
        return e;
    }
    /**
     * @TODO 根據元素索引位置獲取元素
     * @param index 元素的索引位置
     * @return E 元素e
     */
    public E get(int index) {
        validateIndex(index);
        return (E) this.data[index];
    }
    /**
     * @TODO 將順序表中索引位置為i的元素修改為元素e
     * @param index 元素的索引位置
     * @param e 需要修改成的元素
     * @return true 修改成功標志
     */
    public boolean set(int index, E e) {
        validateIndex(index);
        this.data[index] = e;
        return true;
    }
    @Override
    public String toString() {
        return this.arrayToString(data);
    }
    /**
     * @TODO 獲取字符串形式的順序表中的數組序列
     * @param a 順序表中的數組
     * @return String 字符串形式的順序表中的數組序列
     */
    private String arrayToString(Object[] a) {
        if (a == null)
            return "null";
        int iMax = this.size - 1;
        if (iMax == -1)
            return "[]";
        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0;; i++) {
            b.append(String.valueOf(a[i]));
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }
    /**
     * @TODO 驗證所給索引位置是否合法
     * @param index 給出的索引位置
     */
    private void validateIndex(int index) {
        if (index >= this.size || index <= 0) {
            throw new RuntimeException("數組下標錯誤:" + index);
        }
    }
    /**
     * @TODO 判斷是否需要擴充順序表容量
     * @param currentSize 當前順序表的大小
     */
    private void ensureSize(int currentSize) {
        if (currentSize == capacity) {
            this.capacity = (this.capacity * 3) / 2 + 1;
            Object[] newData = new Object[this.capacity];
            for (int i = 0; i < currentSize; i++) {
                newData[i] = this.data[i];
            }
            this.data = newData;
        }
    }
}

主要注意上述3個私有成員變量,如下:

// 順序表長度
private int size;
// 順序表中數組的初始化長度
private int capacity;
// 順序表默認數組為null
private Object[] data = null; 

如同注釋解釋的那樣,size用來表示順序表的長度,data用來表示數組,而capacity用來表示數組的長度.
相信data應該比較好理解,而對應的兩個長度變量相對難理解一些,下面解釋一下:

  • size指的是對外界訪問這個順序表的長度時展示的值,是順序表中數據元素的個數,隨順序表插入和刪除操作而會進行改變;
  • capacity表示的是data數組的長度,實際上也是整個順序表的容量,在順序表初始化的時候可以賦值,或者之後可以調用順序表的擴容來進行改變;
  • size是小於等於capacity的。

這裡主要講講順序表的插入和刪除:
順序表的插入演示如圖所示:

根據圖片可以看出插入一個元素後,插入位置之後的元素都需要向後移動一個位置。
刪除操作則是插入操作的逆過程,刪除位置之後的元素都需要向前移動一個位置。

時間復雜度分析:

  • 在順序表進行存入,查找和修改時,平均時間復雜度都是O(1);
  • 而在進行插入和刪除操作時,最快時為O(1),最慢時為O(n),所以平均時間復雜度為O(n)。

解釋:上述的存入和插入有區別,存入表示存儲在數組末尾,而插入表示插入在任意位置。

優缺點分析:
優點:

  • 不用為表示表中數據元素之間的邏輯關系而增加額外的存儲空間;
  • 可以快速的存取表中任意位置的元素。
    缺點:

  • 插入和刪除操作需要移動大量元素;

  • 當線性表的長度變化較大的時候,很難確定存儲空間的容量;
  • 容易造成存儲空間的“碎片”。

Copyright © Linux教程網 All Rights Reserved