日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(二)使用数组长度实现ADT bag(java)

發布時間:2023/12/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (二)使用数组长度实现ADT bag(java) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1.使用固定大小的數組實現ADT bag 包

  1.1?一組核心方法

  1.2?實現核心方法

? ? 1.3 讓實現安全

  1.4?測試核心方法

  1.5?實現更多的方法

  1.6?刪除項的方法

  1.7 測試

  1.8?發現總結

2.使用可變大小的數組實現ADT包

  2.1 可變大小數組

  2.2 包的新實現

  2.3 使用數組實現ADT包的優缺點

?

?

1. 使用固定大小的數組實現ADT bag包

1.1?一組核心方法

  基于數組實現的ADT包ArrayBag,實現接口BagInterface,接口中定義了泛型T,在ArrayBag的定義中也用到了這個泛型。對于定義難懂的類(ArrayBag)有不少方法,不應該定義整個類,然后試圖去測試它。而是定義一組核心方法(core mehod來實現并測試這些方法,然后再繼續定義中的其他部分(可以集中注意力,簡化任務)。核心方法:這樣的方法應該是類的重要目的,且允許合理的測試。有時稱一組核心方法為核心組(core?group)。

  對于Bag這樣的集合,添加元素add方法是一個基本操作,如果add不成功,remove無從談起。所以add方法去核心方法之一。測試add,需要能看見Bag內容的方法toArray,也是核心方法之一。構造方法也是基本的,另外,核心方法可能調用的任何方法也是核心組的一部分。比如add需要判斷是否bag已滿isArrayFull。

  核心方法:(在這些核心方法能正確工作之前,先不實現其余方法)

  • 構造方法?
  • public boolean?add(T newEntry)
  • public T[]?toArray()
  • private boolean?isArrayFull()

  注:像add和remove這樣能改變集合結構的方法,可能是與實現最緊密的方法。一般,這類方法的定義應該先于類中的其他方法。但因為add正確之前不能remove,所以remove實現放在add完成后且進行充分測試后進行。

  程序設計技巧:當定義一個類時,實現并測試一組核心方法。從向對象集合添加對象及與之相關的方法開始

1.2?實現核心方法

  數據域:對象數組,容量(默認容量或用戶提供)

private final T[] bag;

private int numberOfEntries;

private static final int DEFAULT_CAPACITY = 25;

  加入類ArrayBag的UML表示:

??

  程序設計技巧:終態數組

  通過聲明bag是類ArrayBag的一個終態數據成員,可知變量bag中的引用不能改,但是數據元素bag[0]等可改,但是要防止客戶直接修改bag元素,以防數組內容受到惡意毀壞。

  構造方法:

  注意:

數組bag的泛型問題:

bag = new T[capacity]; // syntax error 分配數組時不能使用泛型

---> 轉為object:

bag?= new Object[capacity]; // imcompatible types不能將object數組賦給T型數組,兩個類型不兼容?---->?轉型

bag = (T[])new Object[capacity]; // 編譯警告,編譯想保證將數組中的每項從類型object轉為T都安全,有問題語句前寫注釋使編譯忽略這個警告:@SuppressWarning(“unchecked”),該注釋只能放在方法定義或變量聲明之前 ---> 找個中間變量再聲明一次

// The cast is safe because the new array contains null entries.

@SuppressWarning(“unchecked”)

T[] tempBag = (T[])?new Object[capacity];

bag = tempBag;

  注:禁止編譯警告

  要禁止編譯程序給出的未檢查轉型警告,可以在標記的語句之前寫

  @SuppressWarning(“unchecked”)

  注意,這條命令只能放在方法定義或變量聲明之前。應該包含一條注釋,對禁止編譯程序警告做出解釋。

  類的框架:

/*** A class of bags whose entries are stored in a fixed-size array.* @author Administrator** @param <T>*/ public final class ArrayBag<T> implements BagInterface<T> { private final T[] bag; private int numberOfEntries; private static final int DEFAULT_CAPACITY = 25;/*** Creates an empty bag whose initial capacity is 25.*/ public ArrayBag() { this(DEFAULT_CAPACITY); } // end default constructor/*** Creats an empty bag having a given initial capacity.* @param capacity: The integer capacity desired.*/ public ArrayBag(int capacity) { // The cast is safe because the new array contains null entries. @SuppressWarnings("unchecked") T[] tempBag = (T[])new Object[capacity]; // Unchecked entries. bag = tempBag; numberOfEntries = 0; } // end constructor/*** Gets the current number of entries in this bag.* @return: The integer number of entries currently in the bag.*/ @Override public int getCurrentSize() { // TODO Auto-generated method stub return 0; } // end getCurrentSize/*** Sees whether this bag is empty.* @return: True if the bag is empty, or false if not.*/ @Override public boolean isEmpty() { // TODO Auto-generated method stub return false; } // end isEmpty/*** Adds a new entry to this bag.* @param newEntry: The object to be added as a new entry.* @return: True if the addition is successful, or false if not.*/ @Override public boolean add(T newEntry) { // TODO Auto-generated method stub return false; } // end add/*** Removes one unspecified entry from this bag, if possible.* @return: Either the removed entry, if the removel was successful, or null.*/ @Override public T remove() { // TODO Auto-generated method stub return null; } // end remove/*** Removes one occurrence of a given entry from this bag, if possible.* @param anEntry: The entry to be removed.* @return: True if the removal was successful, or false if not.*/ @Override public boolean remove(T anEntry) { // TODO Auto-generated method stub return false; } // end remove/*** Removes all entries from this bag.*/ @Override public void clear() { // TODO Auto-generated method stub } // end clear/*** Counts the number of times a given entry appears in this bag.* @param anEntry: The entry to counted.* @return: The number of times anEntry appears in the bag.*/ @Override public int getFrequencyOf(T anEntry) { // TODO Auto-generated method stub return 0; } // end getFrequencyOf/*** Tests whether this bag contains a given entry.* @param anEntry: The entry to locate.* @return: True if the bag contains anEntry, or false if not.*/ @Override public boolean contains(T anEntry) { // TODO Auto-generated method stub return false; } // end contains/*** Retrieves all entries that are in this bag.* @return: A newly allocated array of all the entries in the bag.* Note: If the bag is empty, the returned array is empty.*/ @Override public T[] toArray() { // TODO Auto-generated method stub return null; } // end toArray// Returns true if the arraybag is full, or false if not. private boolean isArrayFull() { return numberOfEntries == 0; } // end isArrayFull } // end class ArrayBag

  程序設計技巧:當定義實現接口的類時,從接口中復制它們來添加類中公有方法的注釋和頭。使用這種方式,方便在實現時檢查每個方法的規格說明。另外,維護代碼的人也容易訪問這些規格說明。

設計決策:當數組中裝了一部分數據時,包的項應該放在數組的哪些位置

添加第一個項:數組中第一個,下標為0;

項是否連續:關于計劃中的實現方案,必須確定某些事實或斷言,以便每個方法的動作不會對其他方法產生不利。(toArray必須知道add將項放在哪里)(remove需要保證項連續嗎?)

  方法add:如果包滿了,則不添加,返回false;否則,將新元素添加到最后一個元素后面。

/*** Adds a new entry to this bag.* @param newEntry: The object to be added as a new entry.* @return: True if the addition is successful, or false if not.*/ @Override public boolean add(T newEntry) {if(isArrayFull()) {return false;}else {// Assertion : result is true herebag[numberOfEntries++] = newEntry;return true;} // end if } // end add

  方法isArrayFull:包中項數與包容量相等時,包滿返回true。

// Returns true if the arraybag is full, or false if not. private boolean isArrayFull() {return numberOfEntries >= bag.length; } // end isArrayFull

   方法toArray:獲取包中的項,將它們返回到客戶新分配的數組內。分配數組處理與構造方法相同。

/*** Retrieves all entries that are in this bag.* @return: A newly allocated array of all the entries in the bag.* Note: If the bag is empty, the returned array is empty.*/ @Override public T[] toArray() {// The cast is safe because the new array contains null entries.@SuppressWarnings("unchecked")T[] result = (T[])new Object[numberOfEntries]; // Unchecked castfor(int i = 0; i < numberOfEntries; i++) {result[i] = bag[i];} // end forreturn result; } // end toArray

1.3 讓實現安全

 程序中檢查可能出現的錯誤來練習有安全機制的程序設計(fail-safe programming)。安全可靠程序設計(safe and secure programming)通過驗證輸入給方法的數據和參數的合法性,消除方法的副作用,對客戶和使用者的行為不做任何假設。

安全說明:保護ADT實現的完整性

兩個問題:

  • ?若構造方法沒有完全執行,可能發生什么?完成初始化之前拋異常,入侵者捕獲異常或錯誤,試圖使用部分初始化的對象;
  • 客戶試圖創建一個容量超出給出范圍的包,會發生什么?

如果這兩個動作可能會導致問題,則必須阻止。

增加兩個數據域:

private boolean initialized = false; private static final int MAX_CAPACITY = 10000;

修改構造方法:

  判斷客戶參數和最大容量,大于拋出異常

  內存不足小于等于最大容量,系統是否能夠分配成功?錯誤OutOfMemoryError黑客捕獲這個異常,使用部分初始化的數據 ---> 利用initialized的狀態判斷是否執行方法

public ArrayBag(int capacity) {if(capacity <= MAX_CAPACITY) {// The cast is safe because the new array contains null entries.@SuppressWarnings("unchecked")T[] tempBag = (T[])new Object[capacity]; // Unchecked entries.bag = tempBag;numberOfEntries = 0;initialized = true; // Last action }else {throw new IllegalStateException("Attempt to create a bag whose "+ "capacity exceeds allowed maximum.");} } // end constructor

  方法如何利用intialized變量:任何方法執行前都要確保數據域initialized的值為真。若為假,方法可以拋出一個異常。

public boolean add(T newEntry) {if(initialized) {boolean result = true;if(isArrayFull()) {result = false;}else {// Assertion : result is true herebag[numberOfEntries++] = newEntry;} // end ifreturn result;}else {throw new SecurityException("ArrayBag object is not initialized properly.");} } // end add

  多個方法都要判斷initialized,所以包裝為方法:

// Throws an exception if this ovject is not initialized. private void checkInitialized() {if(!initialized) {throw new SecurityException("ArrayBag object is not initialized properly.");} } // end checkInitializedpublic boolean add(T newEntry) {checkInitialized();boolean result = true;if(isArrayFull()) {result = false;}else {// Assertion : result is true herebag[numberOfEntries++] = newEntry;} // end ifreturn result; } // end addpublic T[] toArray() {checkInitialized();// The cast is safe because the new array contains null entries.@SuppressWarnings("unchecked")T[] result = (T[])new Object[numberOfEntries]; // Unchecked castfor(int i = 0; i < numberOfEntries; i++) {result[i] = bag[i];} // end forreturn result; } // end toArray

安全說明:

  • ?將類的大多數數據域聲明為私有的,如果不是全部。任何公有數據域都應該是靜態和終態的,且有常量值;
  • 避免那些掩蓋代碼安全性的所謂聰明的邏輯;
  • 避免重復代碼。相反,將這樣的代碼封裝為一個可供其他方法調用的私有方法;
  • 當構造方法調用一個方法時,確保這個方法不能被重寫。

  安全說明:終態類(ArrayBag是一個終態類final class,不會被繼承,確保程序員不能繼承來改變它的行為,比非終態類安全)

1.4?測試核心方法

  準備。已經實現三個核心方法,進行測試。其他需要實現的方法設為存根(stub),即一個不完整定義的方法。僅需要讓語法檢查器通過即可,return一個啞值,Boolean返回false,對象返回null,void方法為空方法體。如果想在測試程序中調用存根,應該顯示一條信息來報告它被調用過。

  測試程序。(默認容量和超容量)

/*** A test of the constructors and the methods add and toArray,* as defined in the first draft of the class ArrayBag.* @author Administrator**/ public class ArrayBagDemo1 {public static void main(String[] args) {// Adding to an initially empty bag with sufficient capacitySystem.out.println("Testing an initially empty bag with the capacity to hold at least 6 strings:");BagInterface<String> aBag = new ArrayBag<>();String[] contentsBag1 = {"A", "B", "A", "D", "B", "C"};testAdd(aBag, contentsBag1);System.out.println("\nTesting an initially empty bag that will be filled to capacity:");aBag = new ArrayBag<>(7);String[] contentsOfBag2 = {"A", "B", "A", "C", "B", "C", "D", "another string"};testAdd(aBag, contentsOfBag2);} // end main// Tests the method add.public static void testAdd(BagInterface<String> aBag, String[] content) {System.out.println("Adding the following " + content.length + " strings to the bag: ");for(int index = 0; index < content.length; index++) {if(aBag.add(content[index])) {System.out.print(content[index] + " ");}else {System.out.print("\nUnable to add " + content[index] + " to the bag.");}} // end for System.out.println();displayBag(aBag);} // end testAdd// Tests the method thArray while displaying the bag.private static void displayBag(BagInterface<String> aBag) {System.out.println("The bag contains the following string(s):");Object[] bagArray = aBag.toArray();for(int index = 0; index < bagArray.length; index++) {System.out.print(bagArray[index] + " ");} // end for System.out.println();} // end displayBag } // end ArrayBagDemo1

output:

Testing an initially empty bag with the capacity to hold at least 6 strings:

Adding the following 6 strings to the bag:

A B A D B C

The bag contains the following string(s):

A B A D B C

?

Testing an initially empty bag that will be filled to capacity:

Adding the following 8 strings to the bag:

A B A C B C D

Unable to add another string to the bag.

The bag contains the following string(s):

A B A C B C D

?

  程序設計技巧:方法的全貌測試還應該包括實參取值范圍在合理范圍內外的情況。

1.5?實現更多的方法

  方法isEmptygetCurrentSize

  可以更早的定義它們,而不是為它們寫存根。

public int getCurrentSize() {return numberOfEntries; } // end getCurrentSizepublic boolean isEmpty() {return numberOfEntries == 0; } // end isEmpty

  方法getFrequencyOf.(比較對象使用equals)

public int getFrequencyOf(T anEntry) {checkInitialization();int count = 0;for(int index = 0; index < numberOfEntries; index++) {if(bag[index].equals(anEntry)) {count++;} // end if} // end forreturn count; } // end getFrequencyOf

  方法contains。

public boolean contains(T anEntry) {checkInitialization();boolean found = false;for(int index = 0; index < numberOfEntries; index++) {if(bag[index].equals(anEntry)) {found = true;break;}}return found; } // end contains

  測試:

public class ArrayBagDemo2 {public static void main(String[] args) {BagInterface<String> aBag = new ArrayBag<>();boolean created = aBag.isEmpty();System.out.println(created);aBag.add("wang");aBag.add("pu");aBag.add("wang");int size = aBag.getCurrentSize();System.out.println(size);System.out.println(aBag.contains("pu"));System.out.println(aBag.contains("he"));int count = aBag.getFrequencyOf("wang");System.out.println(count);}}

output:

true

3

true

false

2

1.6?刪除項的方法

  方法clear(remove方法將調用checkInitialization,所以clear不需要顯式地調用它)

public void clear() {while(!isEmpty()) {remove();}} // end clear

  刪除不確定項remove。只要bag不空,就刪除一個項并將項返回

public T remove() {checkInitialization();T temp = null;if(numberOfEntries > 0) {temp = bag[numberOfEntries - 1];bag[numberOfEntries - 1] = null;numberOfEntries--;} // end ifreturn temp; } // end remove

  安全說明:將數組元素bag[numberOfEntries-1]設置null,標記被刪除對象可進行垃圾回收,并防止惡意代碼來訪問它。

  安全說明:在正確計數后更新計數器。刪除數組最后一項后才將numberOfEntries1,雖然剛開始減1會避免重復,但時間上微不足道的節省不值得冒太早減小計數器帶來的不安全風險。

  刪除給定項,remove。多次只刪除第一次,刪除后需要將該位置補上,因為不需要維護包中項的具體次序,所以只需要將最后一項移過來即可

public boolean remove(T anEntry) {checkInitialization();boolean result = false;if(numberOfEntries > 0) {for(int index = 0; index < numberOfEntries; index++) {if(bag[index].equals(anEntry)) {bag[index] = bag[numberOfEntries - 1];bag[numberOfEntries - 1] = null;numberOfEntries--;result = true;break;} // if} // end for} // end ifreturn false;} // end remove

  刪除最后一項和remove相同,抽出共同部分removeEntry

// Removes and returns the entry at a given index within the array bag.// If no such entry exists, return null.// Preconditions: 0 <= givenIndex < numberOfEntries;// checkInitialization has been called.private T removeEntry(int givenIndex) {T result = null;if (!isEmpty() && (givenIndex >= 0)) {result = bag[givenIndex]; // Entry to removebag[givenIndex] = bag[numberOfEntries - 1]; // Replace entry with last entrybag[numberOfEntries - 1] = null; // Remove last entrynumberOfEntries--;} // end ifreturn result; } // end removeEntry

  此時remove

public T remove() {checkInitialization();T result = removeEntry(numberOfEntries - 1);return result;} // end removepublic boolean remove(T anEntry) {checkInitialization();int index = getIndexOf(anEntry);T result = removeEntry(index);return anEntry.equals(result);} // end remove

  需要索引函數,返回項的位置索引

// Locates a given entry within the array bag.// Returns the index of the entry, if bocated, or -1 otherwise.private int getIndexOf(T anEntry) {int getIndex = -1;if (numberOfEntries > 0) {for (int index = 0; index < numberOfEntries; index++) {if (bag[index].equals(anEntry)) {getIndex = index;break;} // if} // end for} // end ifreturn getIndex;} // end getIndexOf/* 正向思考private int getIndexOf(T anEntry) {int where = -1;boolean stillLooking = true;int index = 0;while (stillLooking && (index < numberOfEntries)){if (anEntry.equals(bag[index])){stillLooking = false;where = index;} // end ifindex++;} // end whilereturn where;} // end getIndexOf*/

  利用getIndexOf方法修改contains方法需要索引函數,返回項的位置索引

public boolean contains(T anEntry) {checkInitialization();return getIndexOf(anEntry) > -1;} // end contains

 因為已經修改了contains,所以需要再次測試。

 設計決策:什么方法應該調用checkInitialization?

  可以在直接涉及數組bag的每個方法都調用,不過更靈活的是,私有方法getIndexOf和removeEntry直接訪問bag,但它們不調用,為什么?若調用,則在共有方法中被調兩次,所以規定在共有方法中調用,并為這兩個私有方法添加一個前置條件來說明checkInitialization必須要先調用(只給實現者和維護者使用)。私有方法只實現一個已定的任務,不再為第二任務負責。

  程序設計技巧:即使可能已經有了方法的正確定義,但如果想到了一個更好的實現,也不要猶豫地取修改它。肯定要再次測試方法!

1.7?測試

/*** A demostration of the class ArrayBag* @author Administrator**/ public class ArrayBagDemo {public static void main(String[] args) {String[] contentsOfBag = {"A", "A", "B", "A", "C", "A"};// Tests on an empty bagBagInterface<String> aBag = new ArrayBag<>(contentsOfBag.length);System.out.println("Testing an initially empty bag:");testIsEmpty(aBag, true);String[] testStrings1 = {"", "B"};testFrequency(aBag, testStrings1);testContains(aBag, testStrings1);testRemove(aBag, testStrings1);// Adding stringsSystem.out.println("Adding " + contentsOfBag.length + " strings to an initially empty bag "+ "with the capacity to hold more than " + contentsOfBag.length + " strings:");testAdd(aBag, contentsOfBag);// Tests on a bag that is not emptytestIsEmpty(aBag, false);String[] testStrings2 = {"A", "B", "C", "D", "A"};testFrequency(aBag, testStrings2);testContains(aBag, testStrings2);// Removing stringsString[] testStrings3 = {"", "B", "A", "C", "Z"};testRemove(aBag, testStrings3);System.out.println("\nClearing the bag:");aBag.clear();testIsEmpty(aBag, true);displayBag(aBag);}// Tests the method add.public static void testAdd(BagInterface<String> aBag, String[] content) {System.out.println("Adding ");for(int index = 0; index < content.length; index++) {aBag.add(content[index]);System.out.print(content[index] + " ");} // end for System.out.println();displayBag(aBag);} // end testAddprivate static void testRemove(BagInterface<String> aBag, String[] tests) {for (int index = 0; index < tests.length; index++) {String aString = tests[index];if (aString.equals("") || (aString == null)) {// test remove()System.out.println("\nRemoving a string from the bag:");String removedString = aBag.remove();System.out.println("remove() returns " + removedString);}else {// test remove(aString)System.out.println("\nRemoving \"" + aString + "\" from the bag:");boolean result = aBag.remove(aString);System.out.println("remove(\"" + aString + "\") returns " + result);} // end if displayBag(aBag);} // end for } // end testRemove// Tests the method toArray while displaying the bag.private static void displayBag(BagInterface<String> aBag) {System.out.println("The bag contains " + aBag.getCurrentSize() +" string(s), as follows:");Object[] bagArray = aBag.toArray();for (int index = 0; index < bagArray.length; index++) {System.out.print(bagArray[index] + " ");} // end for System.out.println();} // end diaplayBag// Tests the method contains.private static void testContains(BagInterface<String> aBag, String[] tests) {System.out.println("\nTesting the method contains:");for (int index = 0; index < tests.length; index++) {String aString = tests[index];if (!aString.equals("") && (aString != null)) {System.out.println("Does this bag contain " + tests[index] +" ? " + aBag.contains(aString));} // end if} // end for} // end testContains// Tests the method getFrequencyOfprivate static void testFrequency(BagInterface<String> aBag, String[] tests) {System.out.println("\nTesting the method getFrequencyOf:");for (int index = 0; index < tests.length; index++) {String aString = tests[index];if (!aString.equals("") && (aString != null)) { System.out.println("In this bag, the count of " + tests[index] +" is " + aBag.getFrequencyOf(aString));} // end if} // end for} // end testFrequency// Tests the method isEmpty// correctResult indicates what isEmpty should return.private static void testIsEmpty(BagInterface<String> aBag, boolean correctResult) {System.out.println("Testing isEmpty with ");if(correctResult) {System.out.println("an empty bag:");}else {System.out.println("a bag that is not empty:");} // end if System.out.print("isEmpty finds the bag ");if(correctResult && aBag.isEmpty()) {System.out.println("empty: OK.");}else if(correctResult) {System.out.println("not empty, but it is empty: ERROR.");}else if(!correctResult && aBag.isEmpty()) {System.out.println("empty, but it is not empty: ERROR.");}else {System.out.println("not empty: OK.");} // if else System.out.println();} // end testIsEmpty }

1.8?發現總結

  • 先判斷核心方法,實現?---> 測試
  • 實現其他方法?----->?測試
  • 實現方法時,先分析輸入輸出,執行功能,異常處理
  • 注重代碼和功能的復用性,可以再抽象出私有方法,在公共方法中判斷異常等情況,私有方法可以添加前置條件
  • 私有方法只完成已指定的一個功能,不再執行第二任務
  • 已經實現的方法,即使有更好的實現,不要改動,改完后需要再次測試
  • 禁止變異警告需要寫清楚禁止變異程序警告的解釋
  • 防止因初始化分配空間失敗而遭惡意程序調用,需要在使用bag前對初始化是否成功進行判斷(借助于initialized變量?--> 抽象為方法checkInitialization)
  • 在實現接口定義的方法時,可以將接口處對方法的注釋copy到實現類中
  • 對不需要保持次序的數組,remove時,可以直接將最后一項將要remove的項覆蓋即可
  • toArray直接返回數組bag而不是復制數組,用戶能直接訪問這個私有數據,bag[index] = null,會導致數組不連續,破壞bag的完整性
  • 實現安全,考慮各種參數和情況的合法性及異常
  • 像以前的簡便寫法,雖然減少代碼量,但是可能會造成不必要的錯誤,還是需要先考慮安全性
  • 編程時習慣:為public方法寫doc注釋,private方法寫注釋用//,返回時,可以定義一個變量,在最后返回變量即可,不要再代碼內部返回。if, for, while, method, class, interface等,在右括號} 后寫end :} // end if(空格+//+空格+end if);在if, while等開始時,{ 之前可以空一個空格;for循環遍歷時,改i為index。
  • 寫代碼測試時,依然不隨意,保持邏輯和整潔,依然有面向對象思想。

?

2.使用可變大小的數組實現ADT包

2.1 可變大小數組

  一般新數組要兩倍于原始數組的大小。數組復制可以使用Arrays.copyOf(sourceArray, newLength)

  程序設計技巧:當增大數組時,將它的項復制到更大的數組中。應該充分地擴展數組,以減少復制代價的影響。常用的辦法是倍增數組大小。

2.2 包的新實現

  方法:修改ADT包的前一個實現,通過調整數組大小使包的容量僅由計算機可用的內存量來限定。

  • 將類名改為ResizableArrayBag,這樣就能區分兩種實現;
  • 從數組bag的聲明中刪除標識符final,以便可用調整它的大小;
  • 修改構造方法的名字以匹配新的類名;
  • 修改方法add的定義,讓它總能容納新項。該方法永遠不會返回假,因為包永遠不會滿。

  方法add:

public boolean add(T newEntry) {checkInitialization();if(isArrayFull()) {doubleCapacity();} // end if// Assertion : result is true herebag[numberOfEntries++] = newEntry;return true; } // end add

// Doubles the size of the array bag.

private?void?doubleCapacity() {

}

  增加容量需要檢查是否超出最大容量MAX_CAPACITY.構造方法中也需要同樣檢查,定義私有方法checkCapacity。

// Doubles the size of the array bag.private void doubleCapacity() {int newLength = 2 * bag.length;checkCapacity(newLength);bag = Arrays.copyOf(bag, newLength);} // end doubleCapacityprivate void checkCapacity(int capacity) {if (capacity > MAX_CAPACITY) {throw new IllegalStateException("Attempt to create a bag whose "+ "capacity exeeds allowed maximun of " + MAX_CAPACITY);} // end if} // end checkCapacity

  構造方法:

public ResizableArrayBag(int capacity) {checkCapacity(capacity);// The cast is safe because the new array contains null entries.@SuppressWarnings("unchecked")T[] tempBag = (T[])new Object[capacity]; // Unchecked entries.bag = tempBag;numberOfEntries = 0;initialized = true; // Last action } // end constructor

  增加構造方法:

/*** Creates a bag containing given entries.* @param contents: An array of objects.*/public ResizableArrayBag(T[] contents) {checkCapacity(contents.length);bag = Arrays.copyOf(contents, contents.length);numberOfEntries = contents.length;initialized = true;} // end constructor

  設計決策:

    方法add布爾方法而不是void:要和接口定義保持一致

    定義私有方法,只被add使用一次:一個方法只執行一個動作的哲學理念。

  程序設計技巧:實現了聲明ADT操作的單一接口的類,應該將定義在接口中的方法聲明為公有方法。但是,類還可以定義私有方法和保護方法。

  測試類:(把測試當做寫代碼的一部分,得學得改!!!

/** A demonstration of the class ResizableArrayBag@author Frank M. Carrano@version 4.0 */ public class ResizableArrayBagDemo {public static void main(String[] args) {// A bag whose initial capacity is smallBagInterface<String> aBag = new ResizableArrayBag<String>(3);testIsEmpty(aBag, true);System.out.println("Adding to the bag more strings than its initial capacity.");String[] contentsOfBag = {"A", "D", "B", "A", "C", "A", "D"};testAdd(aBag, contentsOfBag);testIsEmpty(aBag, false);String[] testStrings2 = {"A", "B", "C", "D", "Z"};testFrequency(aBag, testStrings2);testContains(aBag, testStrings2);// Removing stringsString[] testStrings3 = {"", "B", "A", "C", "Z"};testRemove(aBag, testStrings3);System.out.println("\nClearing the bag:");aBag.clear();testIsEmpty(aBag, true);displayBag(aBag);} // end main// Tests the method add.private static void testAdd(BagInterface<String> aBag, String[] content){System.out.print("Adding to the bag: ");for (int index = 0; index < content.length; index++){aBag.add(content[index]);System.out.print(content[index] + " ");} // end for System.out.println();displayBag(aBag);} // end testAdd// Tests the two remove methods.private static void testRemove(BagInterface<String> aBag, String[] tests){for (int index = 0; index < tests.length; index++){String aString = tests[index];if (aString.equals("") || (aString == null)){// test remove()System.out.println("\nRemoving a string from the bag:");String removedString = aBag.remove();System.out.println("remove() returns " + removedString);}else{// test remove(aString)System.out.println("\nRemoving \"" + aString + "\" from the bag:");boolean result = aBag.remove(aString);System.out.println("remove(\"" + aString + "\") returns " + result);} // end if displayBag(aBag);} // end for} // end testRemove// Tests the method isEmpty.// correctResult indicates what isEmpty should return. private static void testIsEmpty(BagInterface<String> aBag, boolean correctResult){System.out.print("Testing isEmpty with ");if (correctResult)System.out.println("an empty bag:");elseSystem.out.println("a bag that is not empty:");System.out.print("isEmpty finds the bag ");if (correctResult && aBag.isEmpty())System.out.println("empty: OK.");else if (correctResult)System.out.println("not empty, but it is empty: ERROR.");else if (!correctResult && aBag.isEmpty())System.out.println("empty, but it is not empty: ERROR.");elseSystem.out.println("not empty: OK."); System.out.println();} // end testIsEmpty// Tests the method getFrequencyOf.private static void testFrequency(BagInterface<String> aBag, String[] tests){System.out.println("\nTesting the method getFrequencyOf:");for (int index = 0; index < tests.length; index++)System.out.println("In this bag, the count of " + tests[index] + " is " + aBag.getFrequencyOf(tests[index]));} // end testFrequency// Tests the method contains.private static void testContains(BagInterface<String> aBag, String[] tests){System.out.println("\nTesting the method contains:");for (int index = 0; index < tests.length; index++)System.out.println("Does this bag contain " + tests[index] + "? " + aBag.contains(tests[index]));} // end testContains// Tests the method toArray while displaying the bag.private static void displayBag(BagInterface<String> aBag){System.out.println("The bag contains " + aBag.getCurrentSize() +" string(s), as follows:"); Object[] bagArray = aBag.toArray();for (int index = 0; index < bagArray.length; index++){System.out.print(bagArray[index] + " ");} // end for System.out.println();} // end displayBag } // end ResizableArrayBagDemo/*Testing isEmpty with an empty bag:isEmpty finds the bag empty: OK.Adding to the bag more strings than its initial capacity.Adding to the bag: A D B A C A DThe bag contains 7 string(s), as follows:A D B A C A DTesting isEmpty with a bag that is not empty:isEmpty finds the bag not empty: OK.Testing the method getFrequencyOf:In this bag, the count of A is 3In this bag, the count of B is 1In this bag, the count of C is 1In this bag, the count of D is 2In this bag, the count of Z is 0Testing the method contains:Does this bag contain A? trueDoes this bag contain B? trueDoes this bag contain C? trueDoes this bag contain D? trueDoes this bag contain Z? falseRemoving a string from the bag:remove() returns DThe bag contains 6 string(s), as follows:A D B A C ARemoving "B" from the bag:remove("B") returns trueThe bag contains 5 string(s), as follows:A D A A CRemoving "A" from the bag:remove("A") returns trueThe bag contains 4 string(s), as follows:C D A ARemoving "C" from the bag:remove("C") returns trueThe bag contains 3 string(s), as follows:A D ARemoving "Z" from the bag:remove("Z") returns falseThe bag contains 3 string(s), as follows:A D AClearing the bag:Testing isEmpty with an empty bag:isEmpty finds the bag empty: OK.The bag contains 0 string(s), as follows: */

2.3 使用數組實現ADT包的優缺點

  數組易于使用,知道下標就能立即訪問。

使用數組來實現ADT包時:

  • 向包中添加項是快的;
  • 刪除未指定的項是快的;
  • 刪除某個項需要找到這個項的時間;
  • 增大數組的大小需要復制項的時間。

轉載于:https://www.cnblogs.com/datamining-bio/p/9617586.html

總結

以上是生活随笔為你收集整理的(二)使用数组长度实现ADT bag(java)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。