一、數組
數組是應用最廣泛的數據存儲結構,它被植入到大部分編程語言中。由於數組十分易懂,所以它被用來介紹數據結構的起點。 數組分爲2種:無序數組與有序數組。有序數組就是無序數組經過排序後結果。另外數組需要有以下這些要求:
1. 我們通常假設數組中是沒有空洞的。
當我們想在數組查找某個元素時,當所有元素都查過了之後,依然沒有查到,就說明數組中不包含此元素。那麼我們如何知道所有的元素都已經查過了呢?按照規則1,只要我們保證數組所有非空元素,都排在數組的前面,那麼當我們遇到第一個空元素時,就說明所有的元素都查找完了。
2. 當刪除數組中一個元素時,這個數組中之後所有的元素位置都會前移一個位置。
例如我們刪除了第二個元素,在java中,就是移除數組對這個對象的引用,只要將對應位置設爲null即可,但是在這裏我們卻不能這樣做,因爲根據規則1,我們查找的時候,遇到第一個爲null的元素的時候,就認爲所有的元素都查找完了,例如現在查找5,那麼就會查不到,因此刪除必須將後面所有的元素都前移一個位置。
3. 如果是無序數組的話,添加一個元素時,總是添加到數組的最後位置。
插入操作同樣要滿足,插入後,數組中依然不能存在空洞,否則查找依然會出現問題,例如現在還有2個位置可以插入,如果我們插入在最後一個位置上,根據規則1,之後在查找的時候又找不到這個元素了。
4. 如果是有序數組的話,添加元素到某個位置時,當前位置的元素與之後的元素都要往後移動一個位置。
在查找的時候,如果有相同的元素,那麼可能會有多個匹配值,那麼到底返回哪個呢?還是全部都返回?爲了方便,我們通常假設數組中沒有相同的元素,因此只需要返回第一個匹配上的值即可。
下面是代碼實現:
public class Array<V> {
private Object[] elements;
private int size = 0;//數組元素的數量
private int capacity;//數組的容量
/**
* 數組容量
*/
public Array(int capacity){
this.capacity = capacity;
if (capacity <= 0) {
throw new IllegalArgumentException("數組容量必須大於0");
}
elements = new Object[capacity];
}
/**
* 插入元素
*/
public void insert(V v){
if (size == capacity -1) {//達到容量限制
throw new IndexOutOfBoundsException("數組已達到最大容量");
}
elements[size++] = v;
}
/**
* 刪除元素
*/
public boolean remove(V v){
for (int i = 0; i < size; i++){
if (elements[i].equals(v)) {
elements[i] = null;//刪除
moveUp(i);
size--;//元素數量-1
return true;
}
}
return false;
}
/**
* 查找元素
*/
public V find(V v){
for (int i = 0; i < size; i++){
if (elements[i].equals(v)) {
return (V)elements[i];
}
}
return null;
}
/**
* 返回指定index的元素
*/
public V get(int index){
if (index > capacity - 1) {
throw new IndexOutOfBoundsException("指定的索引超過數組容量");
}
return (V)elements[index];//null能強轉嗎
}
/**
* 返回數組元素個數
*/
public int size(){
return size;
}
/**
* 顯示所有元素
*/
public void showAll(){
for (int i = 0; i< elements.length; i++){
if (i < size) {
System.out.print(elements[i] + " ");
}else {
System.out.print("null" + " ");
}
}
System.out.println();
}
/**
* 刪除元素後將所有元素都向前移動一位
*/
private void moveUp(int i) {
while (i < size -1) {
elements[i] = elements[++i];
}
elements[size -1] = null;
}
}
在數據結構與算法中,衡量算法的效率是通過時間複雜度和空間複雜度來進行的,下面是一個簡單的介紹:
- 操作 ———————— 時間複雜度
- 插入 ———————— O(1)
- 刪除 ———————— O(n)
- 查找 ———————— O(n)
其中:
O(1)表示,此操作不受數組元素個數的影響,不論數組中現有多少元素,插入操作總是1步就可以完成。
O(N)表示此操作受到數據元素個數的影響,最直觀的感受是,我們可以看到刪除和查找操作,裏面都有一個for循環來迭代數組中的所有元素,假設數組中有N個元素,我們隨機查找或者刪除一個數字,運氣好的情況下,可能1次就查找了,運氣不好,可能所有的N個元素迭代完了,還是沒有找到,根據概率,平均可能需要進行N/2次循環,由於時間複雜度是忽略常數的,因此刪除和查找操作的平均時間複雜度是O(N)。