- BubbleSortApp.java部分
- /*
- * 下述的作業題源自<<Java數據結構和算法(第二版)>>每章結束後留給的問題,
- * 它們涵蓋了每章的所有重點。目地在於自測,以確保自己已經基本理解該章的內容。
- * 題源:第3章 簡單排序
- * 作者:半點閒
- * 時間:2008.7.21 星期一
- *
- * 3.1 bubbleSort.java程序(清單3.1)和BubbleSort專題applet中,in索引變量都是從左
- * 到右移動的,直到找到最大數據項並把它移動到右邊的out變量外。修改bubbleSort()方法,
- * 使它成爲雙向移動的。這樣,in索引先像以前一樣,將最大的數據項從左移到右,當它到達out
- * 變量位置時,它掉頭並把最小的數據項從右移到左。需要兩個外部索引變量,一個在右邊(以
- * 前的out變量),另一個在左邊。
- *
- * 3.4還有一種簡單排序算法是奇偶排序。它的思路是在數組中重複兩趟掃描。第一趟掃描選擇所
- * 有的數據項對,a[j]和a[j+1],j是奇數(j=1,3,5,……)。如果它們的關鍵字的值次序顛倒,
- * 就交換它們。第二趟掃描對所有的偶數數據項進行同樣的操作(j=2,4,6,……)。重複進行這
- * 樣兩趟的排序直到數組全部有序。用oddEvenSort()方法替換bubbleSort.java程序(清單3.1)
- * 中的bubbleSort()方法。確保它可以在不同數據量的排序中運行,還需要算出兩趟掃描的次數。
- * 奇偶排序實際上在多處理器環境中很有用,處理器可以分別同時處理每一個奇數對,然後又同時
- * 處理偶數對。因爲奇數對是彼此獨立的,每一對都可以用不同的處理器比較和交換。這樣可以非
- * 常快速地排序。
- */
- package bubblesortapp;
- /**
- * @author Administrator
- */
- public class Main {
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- // TODO code application logic here
- int maxSize = 100; //array size
- ArrayBub arr; //reference to array
- arr = new ArrayBub(maxSize); // create the array
- arr.insert(77); //insert 10 items
- arr.insert(99);
- arr.insert(44);
- arr.insert(55);
- arr.insert(22);
- arr.insert(88);
- arr.insert(11);
- arr.insert(00);
- arr.insert(66);
- arr.insert(33);
- arr.display(); //display items
- //arr.bubbleSort(); //bubble sort them
- //arr.display(); //display them again
- //編程作業3.4
- System.out.println("奇偶排序兩趟掃描次數共計:" + arr.oddEvenSort());
- arr.display();
- }
- }
- class ArrayBub
- {
- public ArrayBub(int max) //constructor
- {
- a = new long[max]; //create the array
- nElems = 0; // no items yet
- }
- public void insert(long value) //put element into array
- {
- a[nElems] = value; //insert it
- nElems++; //increment size
- }
- public void display() //displays array contents
- {
- for(int j=0; j<nElems; j++) //for each element,
- System.out.print(a[j] + " "); //display it
- System.out.println();
- }
- /**
- * 3.1 bubbleSort.java程序(清單3.1)和BubbleSort專題applet中,in索引變量都是從左
- * 到右移動的,直到找到最大數據項並把它移動到右邊的out變量外。修改bubbleSort()方法,
- * 使它成爲雙向移動的。這樣,in索引先像以前一樣,將最大的數據項從左移到右,當它到達out
- * 變量位置時,它掉頭並把最小的數據項從右移到左。需要兩個外部索引變量,一個在右邊(以
- * 前的out變量),另一個在左邊。
- */
- public void bubbleSort()
- {
- for(int out=nElems-1; out>1; out--) //outer loop (backward)
- {
- int in;
- for(in=0; in<out; in++) //inner loop (forward)
- if( a[in] > a[in+1]) //out of order?
- swap(in, in+1); //swap them
- //編程作業3.1
- for(int j=in; j>0; j--)
- if( a[j] < a[j-1])
- swap(j,j-1);
- }
- }
- /**
- * 3.4還有一種簡單排序算法是奇偶排序。它的思路是在數組中重複兩趟掃描。第一趟掃描選擇所
- * 有的數據項對,a[j]和a[j+1],j是奇數(j=1,3,5,……)。如果它們的關鍵字的值次序顛倒,
- * 就交換它們。第二趟掃描對所有的偶數數據項進行同樣的操作(j=2,4,6,……)。重複進行這
- * 樣兩趟的排序直到數組全部有序。用oddEvenSort()方法替換bubbleSort.java程序(清單3.1)
- * 中的bubbleSort()方法。確保它可以在不同數據量的排序中運行,還需要算出兩趟掃描的次數。
- * 奇偶排序實際上在多處理器環境中很有用,處理器可以分別同時處理每一個奇數對,然後又同時
- * 處理偶數對。因爲奇數對是彼此獨立的,每一對都可以用不同的處理器比較和交換。這樣可以非
- * 常快速地排序。
- */
- public int oddEvenSort()
- {
- int times = 0;
- boolean exchenged = true;
- while (exchenged)
- {
- exchenged = false;
- for(int i=0; i<nElems; i+=2)//偶數部分
- if((i+1) < nElems && a[i] > a[i+1])
- {
- swap(i,i+1);
- ++times;
- exchenged = true;
- }
- for(int i=1; i<nElems; i+=2)//奇數部分
- if((i+1) < nElems && a[i] > a[i+1])
- {
- swap(i,i+1);
- ++times;
- exchenged = true;
- }
- }
- return times;
- }
- /**
- * 使用一個獨立的方法不一定好,因爲方法調用會增加一些額外的消耗。自己的程序裏將交
- * 換操作這段代碼直接放到程序中。
- * @param one
- * @param two
- */
- private void swap(int one, int two)
- {
- long temp=a[one];
- a[one] = a[two];
- a[two] = temp;
- }
- private long[] a; //ref to array a
- private int nElems;//number of data items
- }
- InsertSortApp.java部分
- /*
- * 下述的作業題源自<<Java數據結構和算法(第二版)>>每章結束後留給的問題,
- * 它們涵蓋了每章的所有重點。目地在於自測,以確保自己已經基本理解該章的內容。
- * 題源:第3章 簡單排序
- * 作者:半點閒
- * 時間:2008.7.23 星期三
- *
- * 3.2在isertSort.java程序(清單3.3)中給ArrayIns類加一個median()方法.這個方法將返回
- * 數組的中間值.(回憶一下,數組中一半數據項比中間值大,一半數據項比中間值小。)
- *
- * 3.3在insertSort.java程序(清單3.3)中增加一個名爲noDups()的方法,這個方法從已經有
- * 序的數組中刪掉重複的數據項而不破壞有序性。(可以用insertionSort()方法對數據排序,
- * 或者也可以簡單地用main()方法將數據有序地插入到表中。)一種解決方法是每發現一個重複
- * 的數據,就從這個位置開始到數組結尾都向前移動一個位置,但這樣就導致消耗很長的O(N2)的
- * 時間級,起碼在有很多重複數據項的情況下是這樣的。在設計的算法中,不論有多少重複數據,
- * 要確保數據項最多隻能移動一次。這樣算法只消耗O(N)數量級的時間。
- *
- * 3.5修改insertSort.java程序(清單3.3)中的insertionSort()方法,使它可以計算排序過
- * 程中複製和比較的次數並顯示出總數。爲計算比較的次數,要把內層while循環的兩個條件分開。
- * 用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?與已經基本有
- * 序的數據(僅有很少的數據無序)的情況一樣嗎?從對基本有序數據排序的表現中可得出關於這
- * 個算法效率的什麼結論?
- *
- * 3.6有一個有趣的方法用來刪除數組中相同的數據項。插入排序算法中用一個循環嵌套算法,將
- * 數組中的每一個數據項與其他數據項一一比較。如果要刪除相同的數據項,可以這樣做(參見第
- * 2章第2.6小節)。修改insertSort.java中的insertionSort()方法,使它可以在排序過程中
- * 刪除相同的數據項。方法如下:當找到一個重複數據項的時候,通常用一個小於任何值的關鍵值
- * 來改寫這個相同數據項(如果所有值都是正數,則可取-1)。於是,一般的插入排序算法就會像
- * 處理其他數據項一樣,來處理這個修改了關鍵值的數據項,把它移到下標爲0的位置。從現在開
- * 始,算法可以忽略這個數據項。下一個相同的數據項將被移到下標爲1的位置,依此類推。排序
- * 完成後,所有相同的數據項(現在關鍵值爲-1)都在數組的開頭部分。可以改變數組的容量並
- * 把需要的數據前移動數組下標爲0的位置。
- */
- package insertsortapp;
- /**
- *
- * @author Administrator
- */
- public class Main {
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- int nRet;
- int maxSize = 100; //array size
- ArrayIns arr; //reference to array
- arr = new ArrayIns(maxSize);//create the array
- /*編程作業3.5 問題1:用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?*/
- for(int i=9; i>=0; i--)//1.初始化爲逆序數組
- arr.insert(i);
- arr.display();
- nRet = arr.insertionSort();
- arr.display();
- System.out.println("編程作業3.5 問題1:比較複製總數:" + nRet );
- /*編程作業3.5 問題2:與已經基本有序的數據(僅有很少的數據無序)的情況一樣嗎?*/
- ArrayIns arr1 = new ArrayIns(maxSize);
- arr1.insert(00); //insert 10 items
- arr1.insert(11);
- arr1.insert(22);
- arr1.insert(44);
- arr1.insert(55);
- arr1.insert(33);
- arr1.insert(66);
- arr1.insert(88);
- arr1.insert(77);
- arr1.insert(99);
- arr1.display();
- nRet = arr1.insertionSort();
- arr1.display();
- System.out.println("編程作業3.5 問題2:比較複製總數:" + nRet);
- //編程作業3.3
- ArrayIns arr2;
- arr2 = new ArrayIns(maxSize);
- arr2.insert(00); //insert 10 items
- arr2.insert(11);
- arr2.insert(22);
- arr2.insert(22);
- arr2.insert(44);
- arr2.insert(55);
- arr2.insert(33);
- arr2.insert(55);
- arr2.insert(66);
- arr2.insert(88);
- arr2.insert(77);
- arr2.insert(66);
- arr2.insert(99);
- arr2.display();
- arr2.noDups();//刪除重複項
- arr2.display();
- //編程作業3.2
- System.out.println("中間值:" + arr.median());
- }
- }
- class ArrayIns
- {
- public ArrayIns(int max)//constructor
- {
- a = new long[max]; //create the array
- nElems = 0; //no items yet
- }
- public void insert(long value)//put element into array
- {
- a[nElems] = value; //insert it
- nElems++; //increment size
- }
- public void display()//displays array contents
- {
- for(int j=0; j<nElems; j++) //for each element,
- System.out.print(a[j] + " ");//display it
- System.out.println("");
- }
- /**
- * 3.5修改insertSort.java程序(清單3.3)中的insertionSort()方法,使它可以計算排序過
- * 程中複製和比較的次數並顯示出總數。爲計算比較的次數,要把內層while循環的兩個條件分開。
- * 用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?與已經基本有
- * 序的數據(僅有很少的數據無序)的情況一樣嗎?從對基本有序數據排序的表現中可得出關於這
- * 個算法效率的什麼結論?
- *
- * 3.6有一個有趣的方法用來刪除數組中相同的數據項。插入排序算法中用一個循環嵌套算法,將
- * 數組中的每一個數據項與其他數據項一一比較。如果要刪除相同的數據項,可以這樣做(參見第
- * 2章第2.6小節)。修改insertSort.java中的insertionSort()方法,使它可以在排序過程中
- * 刪除相同的數據項。方法如下:當找到一個重複數據項的時候,通常用一個小於任何值的關鍵值
- * 來改寫這個相同數據項(如果所有值都是正數,則可取-1)。於是,一般的插入排序算法就會像
- * 處理其他數據項一樣,來處理這個修改了關鍵值的數據項,把它移到下標爲0的位置。從現在開
- * 始,算法可以忽略這個數據項。下一個相同的數據項將被移到下標爲1的位置,依此類推。排序
- * 完成後,所有相同的數據項(現在關鍵值爲-1)都在數組的開頭部分。可以改變數組的容量並
- * 把需要的數據前移動數組下標爲0的位置。
- * 註明:這個題目我就不做了,沒有什麼新意。其實就是把noDups()中的代碼和insertionSort()
- * 代碼混合後就能達到上述作業要求。
- */
- public int insertionSort()
- {
- int in, /*被“標記”數據項應該插入的位置*/
- out, /*分界線(“標記”,它左邊的數據項已經局部有序)*/
- nCompar = 0,/*比較計數器*/
- nCopy = 0; /*拷貝計數器*/
- for(out=1; out<nElems; out++)//out=1,數組中至少得有2個數據項。
- {
- long temp = a[out];//移動前,先請“標記”值出列以騰出空間。
- in = out;//開始移動。
- while(in>0)
- {
- if(a[in-1] >= temp)
- {
- a[in] = a[in-1];
- in--;
- nCompar++;
- nCopy++;
- }
- else
- {
- nCompar++;
- break;
- }
- }
- a[in] = temp;//insert marked item
- }
- return nCompar+nCopy;
- }
- public long median()
- {
- return a[nElems / 2];
- }
- /**
- * 關於編程作業3.3
- * 作者述:就目前來講我暫時還想不出在不開闢新的空間,來達到書中作業要求的“要確保
- * 數據項最多隻能移動一次”這個目標。希望查看此源碼的大俠們能給出更高效的方法。
- * 關於下述代碼
- * 下述代碼採用第2章編程作業:2.6 noDup()方法,在比上次嚴格的測試發現了源代碼中隱
- * 蔽的BUG(主要在“調整部份”),現已經修復我的Blog中有詳細說明。
- */
- public void noDups()
- {
- //標記部分
- int nCount = 0; //標記計數器。
- for(int i=0; i<nElems; i++)
- for(int j=0; j<i; j++)
- if(a[j] == a[i])
- {
- if(a[i] != -1) //排除特殊標記
- {
- a[i] = -1; //特殊標記,假設用戶不會輸入負值。
- nCount++;
- }
- }
- //針對第2章編程作業2.6 noDup()方法中存在的BUG修改後的:調整部分
- long[] b = new long[nElems - nCount];
- int nLength = 0;
- int nVariable = 0;//變數,根據-1值變化調整下標。
- for(int i=0; i<nElems; i++)
- {
- if(a[i] != -1)
- {
- b[i - nVariable] = a[i];
- nLength++;
- }
- else
- nVariable++;
- }
- //重新賦值部份
- nElems = nLength;
- a = b;
- }
- private long[] a; //ref to array a
- private int nElems; //number of data items
- }
Java數據結構和算法-作業2-編程部分
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.