Java數據結構和算法-作業2-編程部分

  1. BubbleSortApp.java部分
  2. /*
  3.  * 下述的作業題源自<<Java數據結構和算法(第二版)>>每章結束後留給的問題,
  4.  * 它們涵蓋了每章的所有重點。目地在於自測,以確保自己已經基本理解該章的內容。
  5.  * 題源:第3章 簡單排序
  6.  * 作者:半點閒
  7.  * 時間:2008.7.21 星期一
  8.  * 
  9.  * 3.1 bubbleSort.java程序(清單3.1)和BubbleSort專題applet中,in索引變量都是從左
  10.  * 到右移動的,直到找到最大數據項並把它移動到右邊的out變量外。修改bubbleSort()方法,
  11.  * 使它成爲雙向移動的。這樣,in索引先像以前一樣,將最大的數據項從左移到右,當它到達out
  12.  * 變量位置時,它掉頭並把最小的數據項從右移到左。需要兩個外部索引變量,一個在右邊(以
  13.  * 前的out變量),另一個在左邊。
  14.  * 
  15.  * 3.4還有一種簡單排序算法是奇偶排序。它的思路是在數組中重複兩趟掃描。第一趟掃描選擇所
  16.  * 有的數據項對,a[j]和a[j+1],j是奇數(j=1,3,5,……)。如果它們的關鍵字的值次序顛倒,
  17.  * 就交換它們。第二趟掃描對所有的偶數數據項進行同樣的操作(j=2,4,6,……)。重複進行這
  18.  * 樣兩趟的排序直到數組全部有序。用oddEvenSort()方法替換bubbleSort.java程序(清單3.1)
  19.  * 中的bubbleSort()方法。確保它可以在不同數據量的排序中運行,還需要算出兩趟掃描的次數。
  20.  * 奇偶排序實際上在多處理器環境中很有用,處理器可以分別同時處理每一個奇數對,然後又同時
  21.  * 處理偶數對。因爲奇數對是彼此獨立的,每一對都可以用不同的處理器比較和交換。這樣可以非
  22.  * 常快速地排序。
  23.  */
  24. package bubblesortapp;
  25. /**
  26.  * @author Administrator
  27.  */
  28. public class Main {
  29.     /**
  30.      * @param args the command line arguments
  31.      */
  32.     public static void main(String[] args) {
  33.         // TODO code application logic here
  34.         int maxSize = 100;      //array size
  35.         ArrayBub arr;           //reference to array
  36.         arr = new ArrayBub(maxSize);    // create the array
  37.         
  38.         arr.insert(77);     //insert 10 items
  39.         arr.insert(99);
  40.         arr.insert(44);
  41.         arr.insert(55);
  42.         arr.insert(22);
  43.         arr.insert(88);
  44.         arr.insert(11);
  45.         arr.insert(00);
  46.         arr.insert(66);
  47.         arr.insert(33);
  48.         
  49.         arr.display();      //display items
  50.         //arr.bubbleSort();   //bubble sort them
  51.         //arr.display();      //display them again
  52.         //編程作業3.4
  53.         System.out.println("奇偶排序兩趟掃描次數共計:" + arr.oddEvenSort());
  54.         arr.display();
  55.     }
  56. }
  57. class ArrayBub
  58. {
  59.     public ArrayBub(int max)    //constructor
  60.     {
  61.         a = new long[max];  //create the array
  62.         nElems = 0;         // no items yet
  63.     }
  64.     public void insert(long value)  //put element into array
  65.     {
  66.         a[nElems] = value;  //insert it
  67.         nElems++;           //increment size
  68.     }
  69.     public void display()   //displays array contents
  70.     {
  71.         for(int j=0; j<nElems; j++)         //for each element,
  72.             System.out.print(a[j] + " ");   //display it
  73.         System.out.println();
  74.     }
  75.  /**
  76.  * 3.1 bubbleSort.java程序(清單3.1)和BubbleSort專題applet中,in索引變量都是從左
  77.  * 到右移動的,直到找到最大數據項並把它移動到右邊的out變量外。修改bubbleSort()方法,
  78.  * 使它成爲雙向移動的。這樣,in索引先像以前一樣,將最大的數據項從左移到右,當它到達out
  79.  * 變量位置時,它掉頭並把最小的數據項從右移到左。需要兩個外部索引變量,一個在右邊(以
  80.  * 前的out變量),另一個在左邊。
  81.  */
  82.     public void bubbleSort()
  83.     {
  84.         for(int out=nElems-1; out>1; out--) //outer loop (backward)
  85.         {
  86.             int in;
  87.             for(in=0; in<out; in++)         //inner loop (forward)
  88.                 if( a[in] > a[in+1])        //out of order?
  89.                     swap(in, in+1);         //swap them
  90.             //編程作業3.1
  91.             for(int j=in; j>0; j--)
  92.                 if( a[j] < a[j-1])
  93.                     swap(j,j-1);
  94.         }
  95.     }
  96.  /**
  97.  * 3.4還有一種簡單排序算法是奇偶排序。它的思路是在數組中重複兩趟掃描。第一趟掃描選擇所
  98.  * 有的數據項對,a[j]和a[j+1],j是奇數(j=1,3,5,……)。如果它們的關鍵字的值次序顛倒,
  99.  * 就交換它們。第二趟掃描對所有的偶數數據項進行同樣的操作(j=2,4,6,……)。重複進行這
  100.  * 樣兩趟的排序直到數組全部有序。用oddEvenSort()方法替換bubbleSort.java程序(清單3.1)
  101.  * 中的bubbleSort()方法。確保它可以在不同數據量的排序中運行,還需要算出兩趟掃描的次數。
  102.  * 奇偶排序實際上在多處理器環境中很有用,處理器可以分別同時處理每一個奇數對,然後又同時
  103.  * 處理偶數對。因爲奇數對是彼此獨立的,每一對都可以用不同的處理器比較和交換。這樣可以非
  104.  * 常快速地排序。
  105.  */
  106.     public int oddEvenSort()
  107.     {
  108.         int times = 0;
  109.         boolean exchenged = true;
  110.         
  111.         while (exchenged)
  112.         {
  113.             exchenged = false;
  114.             for(int i=0; i<nElems; i+=2)//偶數部分
  115.                 if((i+1) < nElems && a[i] > a[i+1])
  116.                 {
  117.                     swap(i,i+1);
  118.                     ++times;
  119.                     exchenged = true;
  120.                 }
  121.             
  122.             for(int i=1; i<nElems; i+=2)//奇數部分
  123.                 if((i+1) < nElems && a[i] > a[i+1])
  124.                 {
  125.                     swap(i,i+1);
  126.                     ++times;
  127.                     exchenged = true;
  128.                 }
  129.         }
  130.         return times;
  131.     }
  132.     /**
  133.      * 使用一個獨立的方法不一定好,因爲方法調用會增加一些額外的消耗。自己的程序裏將交
  134.      * 換操作這段代碼直接放到程序中。
  135.      * @param one
  136.      * @param two
  137.      */
  138.     private void swap(int one, int two)
  139.     {
  140.         long temp=a[one];
  141.         a[one] = a[two];
  142.         a[two] = temp;
  143.     }
  144.     private long[] a;  //ref to array a
  145.     private int nElems;//number of data items
  146. }
  147. InsertSortApp.java部分
  148. /*
  149.  * 下述的作業題源自<<Java數據結構和算法(第二版)>>每章結束後留給的問題,
  150.  * 它們涵蓋了每章的所有重點。目地在於自測,以確保自己已經基本理解該章的內容。
  151.  * 題源:第3章 簡單排序
  152.  * 作者:半點閒
  153.  * 時間:2008.7.23 星期三
  154.  * 
  155.  * 3.2在isertSort.java程序(清單3.3)中給ArrayIns類加一個median()方法.這個方法將返回
  156.  * 數組的中間值.(回憶一下,數組中一半數據項比中間值大,一半數據項比中間值小。)
  157.  * 
  158.  * 3.3在insertSort.java程序(清單3.3)中增加一個名爲noDups()的方法,這個方法從已經有
  159.  * 序的數組中刪掉重複的數據項而不破壞有序性。(可以用insertionSort()方法對數據排序,
  160.  * 或者也可以簡單地用main()方法將數據有序地插入到表中。)一種解決方法是每發現一個重複
  161.  * 的數據,就從這個位置開始到數組結尾都向前移動一個位置,但這樣就導致消耗很長的O(N2)的
  162.  * 時間級,起碼在有很多重複數據項的情況下是這樣的。在設計的算法中,不論有多少重複數據,
  163.  * 要確保數據項最多隻能移動一次。這樣算法只消耗O(N)數量級的時間。
  164.  * 
  165.  * 3.5修改insertSort.java程序(清單3.3)中的insertionSort()方法,使它可以計算排序過
  166.  * 程中複製和比較的次數並顯示出總數。爲計算比較的次數,要把內層while循環的兩個條件分開。
  167.  * 用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?與已經基本有
  168.  * 序的數據(僅有很少的數據無序)的情況一樣嗎?從對基本有序數據排序的表現中可得出關於這
  169.  * 個算法效率的什麼結論?
  170.  * 
  171.  * 3.6有一個有趣的方法用來刪除數組中相同的數據項。插入排序算法中用一個循環嵌套算法,將
  172.  * 數組中的每一個數據項與其他數據項一一比較。如果要刪除相同的數據項,可以這樣做(參見第
  173.  * 2章第2.6小節)。修改insertSort.java中的insertionSort()方法,使它可以在排序過程中
  174.  * 刪除相同的數據項。方法如下:當找到一個重複數據項的時候,通常用一個小於任何值的關鍵值
  175.  * 來改寫這個相同數據項(如果所有值都是正數,則可取-1)。於是,一般的插入排序算法就會像
  176.  * 處理其他數據項一樣,來處理這個修改了關鍵值的數據項,把它移到下標爲0的位置。從現在開
  177.  * 始,算法可以忽略這個數據項。下一個相同的數據項將被移到下標爲1的位置,依此類推。排序
  178.  * 完成後,所有相同的數據項(現在關鍵值爲-1)都在數組的開頭部分。可以改變數組的容量並
  179.  * 把需要的數據前移動數組下標爲0的位置。
  180.  */
  181. package insertsortapp;
  182. /**
  183.  *
  184.  * @author Administrator
  185.  */
  186. public class Main {
  187.     /**
  188.      * @param args the command line arguments
  189.      */
  190.     public static void main(String[] args) {
  191.         int nRet;
  192.         int maxSize = 100;  //array size
  193.         ArrayIns arr;       //reference to array
  194.         arr = new ArrayIns(maxSize);//create the array
  195.         
  196.         /*編程作業3.5 問題1:用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?*/
  197.         for(int i=9; i>=0; i--)//1.初始化爲逆序數組
  198.             arr.insert(i);
  199.         arr.display();
  200.         nRet = arr.insertionSort();
  201.         arr.display();
  202.         System.out.println("編程作業3.5 問題1:比較複製總數:" + nRet );
  203.         
  204.         /*編程作業3.5 問題2:與已經基本有序的數據(僅有很少的數據無序)的情況一樣嗎?*/
  205.         ArrayIns arr1 = new ArrayIns(maxSize); 
  206.         arr1.insert(00); //insert 10 items
  207.         arr1.insert(11);
  208.         arr1.insert(22);
  209.         arr1.insert(44);
  210.         arr1.insert(55);
  211.         arr1.insert(33);
  212.         arr1.insert(66);
  213.         arr1.insert(88);
  214.         arr1.insert(77);
  215.         arr1.insert(99);
  216.         arr1.display();
  217.         nRet = arr1.insertionSort();
  218.         arr1.display();
  219.         System.out.println("編程作業3.5 問題2:比較複製總數:" + nRet);
  220.         
  221.         //編程作業3.3
  222.         ArrayIns arr2;
  223.         arr2 = new ArrayIns(maxSize);
  224.         arr2.insert(00); //insert 10 items
  225.         arr2.insert(11);
  226.         arr2.insert(22);
  227.         arr2.insert(22);
  228.         arr2.insert(44);
  229.         arr2.insert(55);
  230.         arr2.insert(33);
  231.         arr2.insert(55);
  232.         arr2.insert(66);
  233.         arr2.insert(88);
  234.         arr2.insert(77);
  235.         arr2.insert(66);
  236.         arr2.insert(99);
  237.         arr2.display();
  238.         arr2.noDups();//刪除重複項
  239.         arr2.display();
  240.         
  241.         //編程作業3.2
  242.         System.out.println("中間值:" + arr.median());
  243.     }
  244. }
  245. class ArrayIns
  246. {
  247.     public ArrayIns(int max)//constructor
  248.     {
  249.         a = new long[max];  //create the array
  250.         nElems = 0;         //no items yet
  251.     }
  252.     public void insert(long value)//put element into array
  253.     {
  254.         a[nElems] = value;  //insert it
  255.         nElems++;           //increment size
  256.     }
  257.     public void display()//displays array contents
  258.     {
  259.         for(int j=0; j<nElems; j++)     //for each element,
  260.             System.out.print(a[j] + " ");//display it
  261.         System.out.println("");
  262.     }
  263.  /**
  264.  * 3.5修改insertSort.java程序(清單3.3)中的insertionSort()方法,使它可以計算排序過
  265.  * 程中複製和比較的次數並顯示出總數。爲計算比較的次數,要把內層while循環的兩個條件分開。
  266.  * 用這個程序測量各種數量的逆序數據排序的複製和比較次數。結果滿足O(N2)嗎?與已經基本有
  267.  * 序的數據(僅有很少的數據無序)的情況一樣嗎?從對基本有序數據排序的表現中可得出關於這
  268.  * 個算法效率的什麼結論?
  269.  *
  270.  * 3.6有一個有趣的方法用來刪除數組中相同的數據項。插入排序算法中用一個循環嵌套算法,將
  271.  * 數組中的每一個數據項與其他數據項一一比較。如果要刪除相同的數據項,可以這樣做(參見第
  272.  * 2章第2.6小節)。修改insertSort.java中的insertionSort()方法,使它可以在排序過程中
  273.  * 刪除相同的數據項。方法如下:當找到一個重複數據項的時候,通常用一個小於任何值的關鍵值
  274.  * 來改寫這個相同數據項(如果所有值都是正數,則可取-1)。於是,一般的插入排序算法就會像
  275.  * 處理其他數據項一樣,來處理這個修改了關鍵值的數據項,把它移到下標爲0的位置。從現在開
  276.  * 始,算法可以忽略這個數據項。下一個相同的數據項將被移到下標爲1的位置,依此類推。排序
  277.  * 完成後,所有相同的數據項(現在關鍵值爲-1)都在數組的開頭部分。可以改變數組的容量並
  278.  * 把需要的數據前移動數組下標爲0的位置。
  279.   * 註明:這個題目我就不做了,沒有什麼新意。其實就是把noDups()中的代碼和insertionSort()
  280.   * 代碼混合後就能達到上述作業要求。
  281.  */
  282.     public int insertionSort()
  283.     {
  284.         int in,         /*被“標記”數據項應該插入的位置*/
  285.             out,        /*分界線(“標記”,它左邊的數據項已經局部有序)*/
  286.             nCompar = 0,/*比較計數器*/
  287.             nCopy = 0;  /*拷貝計數器*/
  288.         
  289.         for(out=1; out<nElems; out++)//out=1,數組中至少得有2個數據項。
  290.         {
  291.             long temp = a[out];//移動前,先請“標記”值出列以騰出空間。
  292.             in = out;//開始移動。
  293.             while(in>0)
  294.             {
  295.                 if(a[in-1] >= temp)
  296.                 {
  297.                     a[in] = a[in-1];
  298.                     in--;
  299.                     nCompar++;
  300.                     nCopy++;
  301.                 }
  302.                 else
  303.                 {
  304.                     nCompar++;
  305.                     break;
  306.                 }
  307.             }
  308.             a[in] = temp;//insert marked item
  309.         }
  310.         return nCompar+nCopy;
  311.     }
  312.     public long median()
  313.     {
  314.         return a[nElems / 2];
  315.     }
  316.     /**
  317.      * 關於編程作業3.3
  318.      * 作者述:就目前來講我暫時還想不出在不開闢新的空間,來達到書中作業要求的“要確保
  319.      * 數據項最多隻能移動一次”這個目標。希望查看此源碼的大俠們能給出更高效的方法。
  320.      * 關於下述代碼
  321.      * 下述代碼採用第2章編程作業:2.6 noDup()方法,在比上次嚴格的測試發現了源代碼中隱
  322.      * 蔽的BUG(主要在“調整部份”),現已經修復我的Blog中有詳細說明。
  323.      */
  324.     public void noDups()
  325.     {
  326.         //標記部分
  327.         int nCount = 0//標記計數器。
  328.         
  329.         for(int i=0; i<nElems; i++)
  330.             for(int j=0; j<i; j++)
  331.                 if(a[j] == a[i])
  332.                 {
  333.                     if(a[i] != -1)  //排除特殊標記
  334.                     {
  335.                         a[i] = -1;  //特殊標記,假設用戶不會輸入負值。
  336.                         nCount++;
  337.                     }
  338.                 }
  339.         //針對第2章編程作業2.6 noDup()方法中存在的BUG修改後的:調整部分
  340.         long[] b = new long[nElems - nCount];
  341.         int nLength = 0;
  342.         int nVariable = 0;//變數,根據-1值變化調整下標。
  343.         
  344.         for(int i=0; i<nElems; i++)
  345.         {
  346.             if(a[i] != -1)
  347.             {
  348.                 b[i - nVariable] = a[i];
  349.                 nLength++;
  350.             }
  351.             else
  352.                 nVariable++;
  353.         }
  354.         //重新賦值部份
  355.         nElems = nLength;
  356.         a = b;
  357.     }
  358.     private long[] a;   //ref to array a
  359.     private int nElems; //number of data items
  360. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章