《Java資料結構和演算法》第二版 Robert lafore 編程作業 第七章
/* 7.1修改partition.java程式(清單7.2),使partitionIt()方法總是用具有最大的 下標值的數組(最右)資料項目作為樞紐,而不是任意一個資料項目。(這和清單7.3 的quickSort.java程式相似。)確保程式對三個或少於三個資料項目的數組也能 執行。為了達到這個目的,需要增加一些額外的語句。 7.2修改quickSort2.java程式(清單7.4)以計算排序中複製和比較的次數,然後顯 示總數。這個程式應該和QuickSort2專題applet的執行效能相同,因此對逆序 排列資料的複製和比較次數是一致的。(記住一次交換是三個複製。) (7.2題沒有做) 7.3在第3章練習題3.2中,提示可以通過排序資料和挑選中間資料項目來求一個資料 集的中心值。讀者可能會想,使用快速排序然後選擇一個中間的資料項目是找中 心值最快的方法,但是還有一個更快的方法。利用劃分演算法求中心值,而不必 對所有的資料項目排序。為了理解它是如何?的,假設在劃分資料時,偶然發 現樞紐最後停在數組中間的位置上。工作就完成了!樞紐右邊的所有資料項目都 大於(或等於)樞紐,而所有左邊的資料項目都小於(或等於)樞紐,所以如果 樞紐停在數組正中間的位置上,那麼它就是中心值。樞紐通常是不會停在數組 中間位置上的,但是可以通過再劃分包含了中間位置資料項的分組來找到它。 假設數組有7個資料項目分布在數組的關鍵字從0到6的單元中。中間位置的資料項目 的下標為3。如果劃分這個數組,並且樞紐停在下標為4的位置上,那麼需要對 下標為0到4的資料項目重新劃分(這個劃分包含了下標為3的資料項目),而不包括 下標為5到6的資料項目。如果樞紐停在下標為2的分區,總是檢查樞紐是否在中間 的位置。最後,樞紐會停在中間位置上的,程式也就結束。因為所需要的劃分 次數比快速排序少,所以這個演算法更快。 擴充編程作業7.1,來尋找一個數組的中心值資料項目。可以使用類似快速排序的 遞迴調用,但是只用來劃分子數組,而不是對整個數組排序。當找到中心值數 據項時這個過程就停止,而不必等數組排序完成之後才停止。 7.4選擇的意思是從一個數組中找出第k大或者第k小的資料項目。例如,要選擇第7大 的資料項目。找中心值(如編程作業7.2)是選擇的一種特殊情況。可以使用同樣 的劃分過程,但不是找中間位置的資料項目,而是找一個指定下標的資料項目。修 改編程作業7.2中的程式,允許選擇任意一個指定資料項目。你的程式能處理多少 的數組呢? 7.5實現本章最後一節所講的基數排序演算法。它應該能處理不同資料量的資料項目, 以及關鍵字位元不同的資料。同時,也應該能夠實現不同基數的排序(可以是 10以外的其他數),但是,除非編寫的程式能顯示不同的基數值,否則會很難 看清啟動並執行情況。 */package chap07;// partition.java// demonstrates partitioning an array// to run this program: C>java PartitionApp////////////////////////////////////////////////////////////////class ArrayPar {private long[] theArray; // ref to array theArrayprivate int nElems; // number of data items// --------------------------------------------------------------public ArrayPar(int max) // constructor{theArray = new long[max]; // create the arraynElems = 0; // no items yet}// --------------------------------------------------------------public void insert(long value) // put element into array{theArray[nElems] = value; // insert itnElems++; // increment size}// --------------------------------------------------------------public int size() // return number of items{return nElems;}// --------------------------------------------------------------public void display() // displays array contents{System.out.print("A=");for (int j = 0; j < nElems; j++)// for each element,System.out.print(theArray[j] + " "); // display itSystem.out.println("");}// --------------------------------------------------------------public int partitionIt(int left, int right, long pivot) {int leftPtr = left - 1; // right of first elemint rightPtr = right + 1; // left of pivotwhile (true) {while (leftPtr < right && // find bigger itemtheArray[++leftPtr] < pivot); // (nop)while (rightPtr > left && // find smaller itemtheArray[--rightPtr] > pivot); // (nop)if (leftPtr >= rightPtr) // if pointers cross,break; // partition doneelse// not crossed, soswap(leftPtr, rightPtr); // swap elements} // end while(true)return leftPtr; // return partition} // end partitionIt()// =============================================================// 編程作業 7.1public int partitionIt(int left, int right) {int leftPtr = left - 1; // right of first elemint rightPtr = right; // left of pivotlong pivot = theArray[right];while (true) {while (leftPtr < right && // find bigger itemtheArray[++leftPtr] < pivot); // (nop)while (rightPtr > left && // find smaller itemtheArray[--rightPtr] > pivot); // (nop)if (leftPtr >= rightPtr) // if pointers cross,break; // partition doneelse// not crossed, soswap(leftPtr, rightPtr); // swap elements} // end while(true)swap(leftPtr, right);return leftPtr; // return partition} // end partitionIt()// =============================================================// 編程作業 7.3public int findMedian(int left, int right) {int leftPtr = left - 1; // right of first elemint rightPtr = right; // left of pivotlong pivot = theArray[right];while (true) {while (leftPtr < right && // find bigger itemtheArray[++leftPtr] < pivot); // (nop)while (rightPtr > left && // find smaller itemtheArray[--rightPtr] > pivot); // (nop)if (leftPtr >= rightPtr) // if pointers cross,break; // partition doneelse// not crossed, soswap(leftPtr, rightPtr); // swap elements} // end while(true)swap(leftPtr, right);int midindex = theArray.length / 2; // 中間位置if (leftPtr == midindex) {return leftPtr;} else if (leftPtr > midindex) {return findMedian(left, leftPtr - 1);} else {return findMedian(leftPtr + 1, right);}}// =============================================================// 編程作業 7.3public long median() {return theArray[findMedian(0, theArray.length - 1)];}// =============================================================// 編程作業 7.4public int findIndex(int left, int right, int index) {int leftPtr = left - 1; // right of first elemint rightPtr = right; // left of pivotlong pivot = theArray[right];while (true) {while (leftPtr < right && // find bigger itemtheArray[++leftPtr] < pivot); // (nop)while (rightPtr > left && // find smaller itemtheArray[--rightPtr] > pivot); // (nop)if (leftPtr >= rightPtr) // if pointers cross,break; // partition doneelse// not crossed, soswap(leftPtr, rightPtr); // swap elements} // end while(true)swap(leftPtr, right);if (leftPtr == index) {return leftPtr;} else if (leftPtr > index) {return findIndex(left, leftPtr - 1, index);} else {return findIndex(leftPtr + 1, right, index);}}// =============================================================public long findKth(int k) {if (k < 1 || k > theArray.length) {return -1;}return theArray[findIndex(0, theArray.length - 1, k - 1)];}// =============================================================// --------------------------------------------------------------public void swap(int dex1, int dex2) // swap two elements{long temp;temp = theArray[dex1]; // A into temptheArray[dex1] = theArray[dex2]; // B into AtheArray[dex2] = temp; // temp into B} // end swap()// --------------------------------------------------------------} // end class ArrayPar// //////////////////////////////////////////////////////////////public class partition {public static void main(String[] args) {int maxSize = 16; // array sizeArrayPar arr; // reference to arrayarr = new ArrayPar(maxSize); // create the arrayfor (int j = 0; j < maxSize; j++) // fill array with{ // random numberslong n = (int) (java.lang.Math.random() * 199);arr.insert(n);}arr.display(); // display unsorted array// long pivot = 99; // pivot value// System.out.print("Pivot is " + pivot);// int size = arr.size();// // partition array// int partDex = arr.partitionIt(0, size-1, pivot);//// System.out.println(", Partition is at index " + partDex);// arr.display(); // display partitioned array// ===================================================// 編程作業 7.1// int size = arr.size();// int partDex = arr.partitionIt(0, size - 1);// System.out.println("Pation is at index " + partDex);// arr.display();// ====================================================// 編程作業 7.3// System.out.println("中間值是:" + arr.median());// arr.display();// ===================================================// 編程作業 7.4System.out.println("第1小的值是:" + arr.findKth(1));arr.display();// ===================================================} // end main()} // end class PartitionApp// //////////////////////////////////////////////////////////////
package chap07;class Link {public long dData; // data itempublic Link next; // next link in list// -------------------------------------------------------------public Link(long dd) // constructor{dData = dd;}// -------------------------------------------------------------public void displayLink() // display this link{System.out.print(dData + " ");}} // end class Linkclass CircleList {private Link current;private int nItems;public CircleList() {current = null;}public void insert(long value) {Link link = new Link(value);if (current == null) {current = link;link.next = link;} else {link.next = current.next;current.next = link;current = link;// 插入元素,current要移動要新元素}nItems++;}public long remove() {// list為空白是沒有考慮,在調用remove之前應該判斷是否為空白long temp = current.next.dData;// 刪掉current的下一個元素if (current.next == current) { // 只有一個元素時current = null;} else {current.next = current.next.next;}nItems--;return temp;}public long peek() { // 返回最早插入的元素// 調用前要判斷是否為空白return current.next.dData;}public Link find(long value) {Link temp = current; // 儲存原來的位置Link result = null;if (current == null) {return result;}do {step(); // 從current的下一個元素開始比較if (current.dData == value) {result = current;current = temp; // 還原current到原來的位置,這樣就不會打亂插入的順序,current指向最後插入的元素return result;}} while (current != temp); // current到達原來的位置,一周迴圈結束return result;}// 往下移一步public void step() { // 調用step()方法後,順序會被打亂if (current != null) {current = current.next;}}public void display() {if (current != null) {Link temp = current;do {step(); // 從current的一下個開始顯示System.out.print(current.dData + " ");} while (current != temp);}System.out.println();}public boolean isEmpty() {return current == null;}public int size() {return nItems;}}// =============================================================================// 編程作業 7.5// 基數排序演算法// 方法一public class RadixSort {// ==============================================// 基數排序演算法// ==============================================// 過程如下:// 初數組 8 12 22 15 20 7 25 18 212 基數為10// 首先按個位排序// 結果是 (20)(12 22 212)(15 25)(7)(8 18)// 然後按十位排序// 結果是 (7 8) (12 212 15 18) (20 22 25)// 然後按百位排序// 結果是 (7 8 12 15 18 20 22 25) 212// 排序結束// ==============================================// 此方法用鏈表暫存元素// ==============================================private static void radixSort(long[] array, int radix, int distance) {// array 為待排序數組// radix 代表基數// distance 代表排序元素的位元 //大於或等於最大的元素的位元int length = array.length;CircleList[] temp = new CircleList[radix];// 用於暫存元素for (int x = 0; x < radix; x++) { // 初始化數組temp[x] = new CircleList();}int divide = 1;for (int i = 0; i < distance; i++) {// 個人覺的運用基數排序實現基數排序的重點在下面這些代碼for (int j = 0; j < length; j++) { // 按各元素相應位上的數字分組int tempindex = (int) (array[j] / divide) % radix;temp[tempindex].insert(array[j]);}int l = 0;for (int k = 0; k < temp.length; k++) { // 把分好組的元素複製回原數組while (!temp[k].isEmpty()) {array[l++] = temp[k].remove();}}divide = divide * radix;}}public static void main(String[] args) {long[] array = { 3, 2, 3, 2, 5, 333, 45566, 2345678, 78, 990, 12, 432, 56 };radixSort(array, 10, 7);for (int i = 0; i < array.length; i++) {System.out.print(" " + array[i]);}}}// =============================================================================