資料結構與演算法分析-順序表 SequenceList
阿新 • • 發佈:2018-12-18
一.基本思路
由於Java和C語言對陣列的限制,陣列在宣告時就要確定長度,雖然C語言可以動態控制記憶體分配,但也需要人為操作,且不會有是否越界的驗證。順序表的功能為可以隨時在陣列內插入、刪除,而不用擔心陣列越界。具體思路為在建立新的順序表時人為設定順序表的長度,當陣列資料存滿後,新建一個長度為原來兩倍的新陣列,將原資料放入新陣列中,並返回新陣列。
操作 | 具體實現思路以及時間複雜度 |
---|---|
新增 | 在資料最後端新增新元素。O(1) |
刪除 | 把要刪除節點後的節點向前移動1個節點。O(n) |
插入 | 把要插入位置上以及之後的向後移動1個節點。O(1) |
查詢 | 取決於查詢演算法。順序遍歷複雜度為O(n) |
二. Java實現
迭代器程式碼:
public interface Iterator<Type>{
boolean hasNext();
Type next();
void remove();
}
陣列程式碼:
public class SequenceList<Type>{ private final int DEFAULT_SIZE = 10; Type[] elements; int size; //構造方法 無參 public SequenceList(){ elements = (Type[])new Object[DEFAULT_SIZE]; //實行強轉 size = 0; } //構造方法 有參 public SequenceList(int size) throws IllegalArgumentException{ if(size<=0) throw new IllegalArgumentException("引數無效:陣列長度必須為正整數"); else{ elements = (Type[])new Object[size]; this.size = 0; } } //返回索引上的元素 public Type get(int index) throws IndexOutOfBoundsException,IllegalArgumentException{ if(index<0||index>=elements.length) throw new IllegalArgumentException("引數無效:陣列索引必須為正整數且小於陣列長度"); else if(index>=size) throw new IndexOutOfBoundsException("索引越界:索引應小於等於陣列長度"); else return elements[index]; } //查詢 這裡只實現最簡單的遍歷查詢 查詢成功返回索引 未找到返回-1 public int find(Type data){ index = 0; for(Type element:elements){ if(element==data) return index; index++; } return -1; } //增長陣列長度 public void ensureCapacity(int newSize) throws IllegalArgumentException{ if(newSize<size) throw new IllegalArgumentException("引數無效:輸入長度必須大於等於陣列長度"); else{ Type[] temp = elements; //儲存原資料 elements = (Type[])Object[newSize]; //新建新陣列 for(int i = 0;i<size;i++){ elements[i] = temp[i]; //把原資料放入陣列 } } } //將陣列長度變為資料實際長度 public void trimToSize(){ this.ensureCapacity(this.size); } //增長陣列長度 public void addLength(int added) throws IllegalArgumentException{ if(added<0) throw new IllegalArgumentException("引數無效:增長長度必須為正整數"); else this.ensureCapacity(elements.length+added); } //在陣列末尾新增元素 public void append(Type obj){ if(size==elements.length) //陣列滿了 this.ensureCapacity(elements.length*2); //建立一個長度為原來兩倍的陣列 elements[size] = obj; size++; } //在陣列指定位置插入 public void insert(Type data,int index) throws IllegalArgumentException,IndexOutOfBoundsException{ if(index<0||index>=elements.length) throw new IllegalArgumentException("引數無效:陣列索引必須為正整數且小於陣列長度"); else if (index>=size) throw new IndexOutOfBoundsException("陣列越界:索引應小於等於陣列長度"); else{ if(size==elements.length) this.ensureCapacity(elements.length*2); for(int i=size;i>index;i--) elements[i] = elements[i-1]; //從末端移動 因為從索引開始移動會覆蓋資料 導致資料丟失 elements[index] = data; size++; } } //刪除元素 public void remove(int index) throws IllegalArgumentException,IndexOutOfBoundsException{ if(index<0||index>=elements.length) throw new IllegalArgumentException("引數無效:陣列索引必須為正整數且小於陣列長度"); else if (index>=size) throw new IndexOutOfBoundsException("陣列越界:索引應小於等於陣列長度"); else{ for(int i=index;i<size-1;i++) //i到size-2的時候已經移動size-1了 elements[i] = elements[i+1]; size--; } } //清空陣列 public void clear(){ elements = (Type[])new Object[DEFAULT_CAPACITY]; size=0; } //判斷陣列是否為空 public boolean isEmpty(){ return size==0; } //返回陣列長度 public int getSize(){ return this.size; } //新建迭代器 public Iterator<Type> iterator(){ return new Iterator(); } //繼承並實現迭代器 private class Iterator<Type> implements Iterator<Type>{ private int index = 0; private Type element; public boolean hasNext(){ return current<getSize(); } public Type next() throws NoSuchElementException{ if(!hasNext()) throw new NoSuchElementException("下標錯誤:沒有下一個元素了"); return get(current++); } public void remove(){ SequenceList.this.remove(current--); } } }