第二章 使用數組實現袋子
第二章 使用數組實現袋子
1.使用固定大小的數組實現ADT袋子
一組核心方法
核心方法:對實現類的意圖是極為重要的,且允許合理的測試,也成為核心組。
- 構造函數
- public boolean add(T anEntity)
- public T[] toArray()
- public boolean isFull()
核心方法的實現
數據域:定義任何方法前,要考慮類的數據域。
private final T[] bag;//袋子用來容納對象的數組 private static final int DEFAULT_CAPACITY=25;//默認數組大小 private int numberOfEntries;//跟蹤袋子中物品當前物品的數量
將數據域加入到UML中
第一個改成:-bag:T []
構造函數:
public ArrayBag() {
this(DEFAULT_CAPACITY);
}
public ArrayBag(int capacity) {
numberOfEntires = 0;
T[] tempBag = (T[]) new Object[capacity];
bag = tempBag;
}
方法add
public boolean add(T newEntity) { boolean result = true; if (isFull()) { result = false; } else { bag[numberOfEntires] = newEntity; numberOfEntires++; } return result; }
方法isFull
public boolean isFull() {
return numberOfEntires == bag.length;
}
方法toArray
方法toArray不能返回bag本身,返回bag本身,就給了客戶直接訪問私有數據的權利。類不應該返回私有的數組數據域的引用。
public T[] toArray() { T[] result = (T[]) new Object[numberOfEntires]; for (int index = 0; index < numberOfEntires; index++) { result[index] = bag[index]; } return result; }
更多方法的實現
(1)方法isEmpty和getCurrentSize
public boolean isEmpty() {
return numberOfEntires==0;
}
public Integer getCurrentSize() {
return numberOfEntires;
}
(2)方法getFrequencyOf public Integer getFrequencyOf(T anEntity) { int counter = 0; for (int i = 0; i < numberOfEntires; i++) { if (bag[i].equals(anEntity)) { counter++; } } return counter; }
(2)方法Contains
public boolean contains(T anEntity) {
boolean flag = false;
for (int i = 0; i < numberOfEntires; i++) {
if (bag[i].equals(anEntity)) {
flag = true;
break;
}
}
return flag;
}
刪除物品的方法
(1)方法clear
public void clear() {
// 調用remove方法,不斷刪除,知道為空
while (!isEmpty()) {
remove();
}
}
(2)刪除一個未特別指定的物品
首先,保證刪除前袋子不為空;其次,從後往前刪除比較簡單; 步驟:訪問該物品,以便返回它 設置該物品的數組元素為null; numberOfEntires值減一。
public T remove() {
T result = null;
if (numberOfEntires > 0) {
result = bag[numberOfEntires - 1];
bag[numberOfEntires - 1] = null;
numberOfEntires--;
}
return result;
}
(3)刪除一個給定的物品
當該物品出現多次,只刪除第一次出現。只需bag[inex]=null;但是,這樣會在數組中產生缺口,袋子內容不再位於連續的數組位置上面,可以通過把後面的元素都往前移動一位來解決,但是耗時。我們不用維護袋子中物品在數組中的位置,所以可以用數組最後一個物品來替換將要移除的物品,然後把數組中最後一個物品刪除。
public boolean remove(T anEntity) {
boolean flag = false;// 未刪除
for (int i = 0; i < numberOfEntires; i++) {
if (anEntity.equals(bag[i])) {
bag[i] = bag[numberOfEntires - 1];
bag[numberOfEntires - 1] = null;
numberOfEntires--;
flag = true;
break;
}
}
return flag;
}
(4)避免重復勞動
私有方法,供兩個remove方法調用
private T remove(int givenIndex) {
T result = null;
if (!isEmpty() && givenIndex >= 0) {
result = bag[givenIndex];
numberOfEntires--;
bag[givenIndex] = bag[numberOfEntires];
bag[numberOfEntires] = null;
}
return result;
}
私有方法,getIndexOf
private int getIndexOf(T anEntity) {
int where = -1;
boolean found = false;
for (int i = 0; !found && i < numberOfEntires; i++) {
if (anEntity.equals(bag[i])) {
found = true;
where = i;
}
}
return where;
}
修改後remove
public T remove() {
T result = remove(numberOfEntires - 1);
return result;
}
修改後remove(T anEntity)
public boolean remove(T anEntity) {
int index = getIndexOf(anEntity);
T result = remove(index);
return anEntity.equals(result);
}
2.使用可變大小的數組實現ADT袋子
固定大小的數組實現ADT袋子,會限制袋子大小。當數組滿了的時候,isFull返回true,add方法返回false。一些應用可以使用這樣容量有限的袋子或者集合,而另一些應用,集合的大小需要無限增長。
詳細過程
假定有一個myArray引用的數組,首先定義oldArray,oldArray引用myArray,創建比myArray大一倍的新數組,讓myArray引用此新數組,然後把oldArray內容復制到myArray中,然後oldArray=null。
代碼 可以用myArray=Arrays.copyOf(myArray,2*myArray.length)
袋子的一種新的實現
確保add的時候,數組不會滿。
數組實現袋子的優缺點
優點:
- 向袋子中增加一個物品的過程是很快的, 在數組末尾刪除和添加物品非常簡單快速,因為我們知道數組末尾的索引。
- 刪除非特定物品也很快。
- 刪除數組中間的特點物品,未了避免在數組中產生缺口,采取數組中最後一個物品替換被刪除物品的策略。
- 允許直接訪問元素,只要知道索引即可。
- 固定大小的數組限制袋子容量。
- 可變大小的數組,需要復制物品到新的數組中,復制的都是數組物品的引用,並沒有占據太多空間,也沒有花費太多時間在移動上。
缺點:
- 刪除一個特點物品需要時間來定位該物品
- 增加數組的大小需要時間來復制它的物品(的引用)。
第二章 使用數組實現袋子