定義
數組(Array)是一種線性表數據結構。它用一組連續的內存空間,來存儲一組具有相同類型的數據。
線性表
顧名思義,線性表就是數據排成像一條線一樣的結構。每個線性表上的數據最多隻有前和後兩個方向。其實除了數組,鏈表、隊列、棧等也是線性表結構。
連續內存,類型相同
我們知道,計算機會給每個內存單元分配一個地址,計算機通過地址來訪問內存中的數據。當計算機需要隨機訪問數組中的某個元素時,它會首先通過下面的尋址公式,計算出該元素存儲的內存地址:
a[i]_address = base_address + i * data_type_size
優劣
優點顯而易見,其時間複雜度僅僅爲 ,但是對於插入或者刪除,都需要通過平移數組來完成操作,這就意味着最壞時間複雜度爲 ,如果容量還需要進行擴容,這是相當耗時的。
個人總結
- Java List 無法存儲基本類型,都需要封住成 Integer 或者 Long 類,而裝箱和拆箱是有很大的性能消耗的。
- 如果數據大小事先已知,並且對數據的操作非常簡單,用不到 ArrayList 提供的大部分方法,也可以直接使用數組。
例子
- 普通數組封裝(不支持擴容)
class Array {
int data[];
int count;
int n;
Array(int capacity) {
data = new int[capacity];
count = 0;
n = capacity;
}
boolean add(int index, int value) {
if (count >= n) {
System.out.println("容量達到最大值");
return false;
}
if (index > count) {
System.out.println("下標越界");
return false;
}
// 從屁股開始,往後移動,將 index 位置空出來
for (int i = count; i > index; i--) {
data[i] = data[i - 1];
}
data[index] = value;
count++;
System.out.println("插入成功:\tvalue:\t" + value + ":\tindex:\t" + index);
System.out.println("data:\t" + toString());
return true;
}
int get(int index) {
if (index >= count) {
return -1;
}
System.out.println("value:\t" + data[index]);
return data[index];
}
boolean delete(int index) {
if (index >= count) {
System.out.println("下標越界");
return false;
}
for (int i = index; i < count - 1; i++) {
data[i] = data[i + 1];
}
data[count - 1] = 0;
count--;
System.out.println("刪除成功 data:\t" + toString());
return true;
}
@Override
public String toString() {
return Arrays.toString(data);
}
public static void main(String[] args) {
Array array = new Array(10);
array.add(0, 1);
array.add(1, 2);
array.add(2, 3);
array.add(3, 4);
array.add(4, 5);
array.add(5, 6);
array.add(6, 7);
array.add(7, 8);
array.add(8,9);
array.add(9,10);
array.delete(9);
System.out.println("get value:\t" + array.get(3));
}
}
輸出結果:
插入成功: value: 1: index: 0
data: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
插入成功: value: 2: index: 1
data: [1, 2, 0, 0, 0, 0, 0, 0, 0, 0]
插入成功: value: 3: index: 2
data: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
插入成功: value: 4: index: 3
data: [1, 2, 3, 4, 0, 0, 0, 0, 0, 0]
插入成功: value: 5: index: 4
data: [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
插入成功: value: 6: index: 5
data: [1, 2, 3, 4, 5, 6, 0, 0, 0, 0]
插入成功: value: 7: index: 6
data: [1, 2, 3, 4, 5, 6, 7, 0, 0, 0]
插入成功: value: 8: index: 7
data: [1, 2, 3, 4, 5, 6, 7, 8, 0, 0]
插入成功: value: 9: index: 8
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
插入成功: value: 10: index: 9
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
刪除成功 data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
value: 4
get value: 4
- 支持擴容的數組
class GenericArray<T> {
T[] data;
int size;
GenericArray(int capacity) {
data = (T[]) new Object[capacity];
size = 0;
}
GenericArray() {
this(10);
}
void checkIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("下標越界");
}
}
void resize(int newSize) {
T[] newData = (T[]) new Object[newSize];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
System.out.println("擴容 capacity:\t" + newSize);
data = newData;
}
T get(int index) {
checkIndex(index);
return data[index];
}
boolean isEmpty() {
return size == 0;
}
void set(int index, T t) {
checkIndex(index);
data[index] = t;
System.out.println("set value:" + " index: " + index + " value: " + t);
System.out.println("data: " + toString());
}
int getCapacity() {
return data.length;
}
int getCount() {
return size;
}
boolean contains(T t) {
for (int i = 0; i < size; i++) {
if (data[i] == t) {
return true;
}
}
return false;
}
int find(T t) {
for (int i = 0; i < size; i++) {
if (data[i] == t) {
return i;
}
}
return -1;
}
void add(int index, T t) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("下標越界");
}
if (size == data.length) {
resize(2 * size);
}
for (int i = size; i > index; i--) {
data[i] = data[i-1];
}
data[index] = t;
size ++;
System.out.println("add data: " + " index: " + index + " value: " + t);
System.out.println("data: " + toString());
}
void addFirst(T t) {
add(0, t);
}
void addLast(T t) {
add(size, t);
}
T remove(int index) {
checkIndex(index);
T t = data[index];
for (int i = index; i < size - 1; i++) {
data[i] = data[i + 1];
}
data[size-1] = null;
size--;
if (size == data.length / 4 && data.length / 2 != 0) {
resize(data.length / 2);
}
System.out.println("remove data: " + " index: " + index + " value: " + t);
System.out.println("data: " + toString());
return t;
}
@Override
public String toString() {
return Arrays.toString(data);
}
public static void main(String[] args) {
GenericArray<String> data = new GenericArray<String>(6);
data.addLast("1");
data.addLast("2");
data.addLast("3");
data.addLast("4");
data.addLast("5");
data.addLast("6");
data.addLast("7");
data.remove(data.getCount()-1);
data.remove(data.getCount()-1);
data.remove(data.getCount()-1);
data.remove(data.getCount()-1);
}
}
輸出結果:
add data: index: 0 value: 1
data: [1, null, null, null, null, null]
add data: index: 1 value: 2
data: [1, 2, null, null, null, null]
add data: index: 2 value: 3
data: [1, 2, 3, null, null, null]
add data: index: 3 value: 4
data: [1, 2, 3, 4, null, null]
add data: index: 4 value: 5
data: [1, 2, 3, 4, 5, null]
add data: index: 5 value: 6
data: [1, 2, 3, 4, 5, 6]
擴容 capacity: 12
add data: index: 6 value: 7
data: [1, 2, 3, 4, 5, 6, 7, null, null, null, null, null]
remove data: index: 6 value: 7
data: [1, 2, 3, 4, 5, 6, null, null, null, null, null, null]
remove data: index: 5 value: 6
data: [1, 2, 3, 4, 5, null, null, null, null, null, null, null]
remove data: index: 4 value: 5
data: [1, 2, 3, 4, null, null, null, null, null, null, null, null]
擴容 capacity: 6
remove data: index: 3 value: 4
data: [1, 2, 3, null, null, null]
參考自極客時間