1. 程式人生 > >Java實現幾種常見排序方法(下) .

Java實現幾種常見排序方法(下) .

 插入排序的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。其具體步驟參見程式碼及註釋。 [java] view plaincopyprint?
  1. /** 
  2.  * 插入排序<br/> 
  3.  * <ul> 
  4.  * <li>從第一個元素開始,該元素可以認為已經被排序</li> 
  5.  * <li>取出下一個元素,在已經排序的元素序列中從後向前掃描</li> 
  6.  * <li>如果該元素(已排序)大於新元素,將該元素移到下一位置</li> 
  7.  * <li>重複步驟3,直到找到已排序的元素小於或者等於新元素的位置</li> 
  8.  * <li>將新元素插入到該位置中</li> 
  9.  * <li>重複步驟2</li>
     
  10.  * </ul> 
  11.  *  
  12.  * @param numbers 
  13.  */
  14. publicstaticvoid insertSort(int[] numbers) {  
  15. int size = numbers.length, temp, j;  
  16. for(int i=1; i<size; i++) {  
  17.         temp = numbers[i];  
  18. for(j = i; j > 0 && temp < numbers[j-1]; j--)  
  19.             numbers[j] = numbers[j-1];  
  20.         numbers[j] = temp;  
  21.     }  
  22. }  

歸併排序是建立在歸併操作上的一種有效的排序演算法,歸併是指將兩個已經排序的序列合併成一個序列的操作。參考程式碼如下:

[java] view plaincopyprint?
  1. /** 
  2.  * 歸併排序<br/> 
  3.  * <ul> 
  4.  * <li>申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列</li> 
  5.  * <li>設定兩個指標,最初位置分別為兩個已經排序序列的起始位置</li> 
  6.  * <li>比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置</li> 
  7.  * <li>重複步驟3直到某一指標達到序列尾</li> 
  8.  * <li>將另一序列剩下的所有元素直接複製到合併序列尾</li> 
  9.  * </ul> 
  10.  * 演算法參考:<a href="http://www.cnitblog.com/intrl/" mce_href="http://www.cnitblog.com/intrl/">Java部落</a> 
  11.  *  
  12.  * @param numbers 
  13.  */
  14. publicstaticvoid mergeSort(int[] numbers, int left, int right) {  
  15. int t = 1;// 每組元素個數
  16. int size = right - left + 1;  
  17. while (t < size) {  
  18. int s = t;// 本次迴圈每組元素個數
  19.         t = 2 * s;  
  20. int i = left;  
  21. while (i + (t - 1) < size) {  
  22.             merge(numbers, i, i + (s - 1), i + (t - 1));  
  23.             i += t;  
  24.         }  
  25. if (i + (s - 1) < right)  
  26.             merge(numbers, i, i + (s - 1), right);  
  27.     }  
  28. }  
  29. /** 
  30.  * 歸併演算法實現 
  31.  *  
  32.  * @param data 
  33.  * @param p 
  34.  * @param q 
  35.  * @param r 
  36.  */
  37. privatestaticvoid merge(int[] data, int p, int q, int r) {  
  38. int[] B = newint[data.length];  
  39. int s = p;  
  40. int t = q + 1;  
  41. int k = p;  
  42. while (s <= q && t <= r) {  
  43. if (data[s] <= data[t]) {  
  44.             B[k] = data[s];  
  45.             s++;  
  46.         } else {  
  47.             B[k] = data[t];  
  48.             t++;  
  49.         }  
  50.         k++;  
  51.     }  
  52. if (s == q + 1)  
  53.         B[k++] = data[t++];  
  54. else
  55.         B[k++] = data[s++];  
  56. for (int i = p; i <= r; i++)  
  57.         data[i] = B[i];  
  58. }  

將之前介紹的所有排序演算法整理成NumberSort類,程式碼

[java] view plaincopyprint?
  1. /** 
  2.  * BubbleSort.class 
  3.  */
  4. package test.sort;  
  5. import java.util.Random;  
  6. /** 
  7.  * Java實現的排序類 
  8.  *  
  9.  * @author cyq 
  10.  *  
  11.  */
  12. publicclass NumberSort {  
  13. /** 
  14.      * 私有構造方法,禁止例項化 
  15.      */
  16. private NumberSort() {  
  17. super();  
  18.     }  
  19. /** 
  20.      * 冒泡法排序<br/> 
  21.      * <ul> 
  22.      * <li>比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。</li> 
  23.      * <li>對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。</li> 
  24.      * <li>針對所有的元素重複以上的步驟,除了最後一個。</li> 
  25.      * <li>持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。</li> 
  26.      * </ul> 
  27.      *  
  28.      * @param numbers 
  29.      *            需要排序的整型陣列 
  30.      */
  31. publicstaticvoid bubbleSort(int[] numbers) {  
  32. int temp; // 記錄臨時中間值
  33. int size = numbers.length; // 陣列大小
  34. for (int i = 0; i < size - 1; i++) {  
  35. for (int j = i + 1; j < size; j++) {  
  36. if (numbers[i] < numbers[j]) { // 交換兩數的位置
  37.                     temp = numbers[i];  
  38.                     numbers[i] = numbers[j];  
  39.                     numbers[j] = temp;  
  40.                 }  
  41.             }  
  42.         }  
  43.     }  
  44. /** 
  45.      * 快速排序<br/> 
  46.      * <ul> 
  47.      * <li>從數列中挑出一個元素,稱為“基準”</li> 
  48.      * <li>重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割之後, 
  49.      * 該基準是它的最後位置。這個稱為分割(partition)操作。</li> 
  50.      * <li>遞迴地把小於基準值元素的子數列和大於基準值元素的子數列排序。</li> 
  51.      * </ul> 
  52.      *  
  53.      * @param numbers 
  54.      * @param start 
  55.      * @param end 
  56.      */
  57. publicstaticvoid quickSort(int[] numbers, int start, int end) {  
  58. if (start < end) {  
  59. int base = numbers[start]; // 選定的基準值(第一個數值作為基準值)
  60. int temp; // 記錄臨時中間值
  61. int i = start, j = end;  
  62. do {  
  63. while ((numbers[i] < base) && (i < end))  
  64.                     i++;  
  65. while ((numbers[j] > base) && (j > start))  
  66.                     j--;  
  67. if (i <= j) {  
  68.                     temp = numbers[i];  
  69.                     numbers[i] = numbers[j];  
  70.                     numbers[j] = temp;  
  71.                     i++;  
  72.                     j--;  
  73.                 }  
  74.             } while (i <= j);  
  75. if (start < j)  
  76.                 quickSort(numbers, start, j);  
  77. if (end > i)  
  78.                 quickSort(numbers, i, end);  
  79.         }  
  80.     }  
  81. /** 
  82.      * 選擇排序<br/> 
  83.      * <ul> 
  84.      * <li>在未排序序列中找到最小元素,存放到排序序列的起始位置</li> 
  85.      * <li>再從剩餘未排序元素中繼續尋找最小元素,然後放到排序序列末尾。</li> 
  86.      * <li>以此類推,直到所有元素均排序完畢。</li> 
  87.      * </ul> 
  88.      *  
  89.      * @param numbers 
  90.      */
  91. publicstaticvoid selectSort(int[] numbers) {  
  92. int size = numbers.length, temp;  
  93. for (int i = 0; i < size; i++) {  
  94. int k = i;  
  95. for (int j = size - 1; j > i; j--) {  
  96. if (numbers[j] < numbers[k])  
  97.                     k = j;  
  98.             }  
  99.             temp = numbers[i];  
  100.             numbers[i] = numbers[k];  
  101.             numbers[k] = temp;  
  102.         }  
  103.     }  
  104. /** 
  105.      * 插入排序<br/> 
  106.      * <ul> 
  107.      * <li>從第一個元素開始,該元素可以認為已經被排序</li> 
  108.      * <li>取出下一個元素,在已經排序的元素序列中從後向前掃描</li> 
  109.      * <li>如果該元素(已排序)大於新元素,將該元素移到下一位置</li> 
  110.      * <li>重複步驟3,直到找到已排序的元素小於或者等於新元素的位置</li> 
  111.      * <li>將新元素插入到該位置中</li> 
  112.      * <li>重複步驟2</li> 
  113.      * </ul> 
  114.      *  
  115.      * @param numbers 
  116.      */
  117. publicstaticvoid insertSort(int[] numbers) {  
  118. int size = numbers.length, temp, j;  
  119. for (int i = 1; i < size; i++) {  
  120.             temp = numbers[i];  
  121. for (j = i; j > 0 && temp < numbers[j - 1]; j--)  
  122.                 numbers[j] = numbers[j - 1];  
  123.             numbers[j] = temp;  
  124.         }  
  125.     }  
  126. /** 
  127.      * 歸併排序<br/> 
  128.      * <ul> 
  129.      * <li>申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列</li> 
  130.      * <li>設定兩個指標,最初位置分別為兩個已經排序序列的起始位置</li> 
  131.      * <li>比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置</li> 
  132.      * <li>重複步驟3直到某一指標達到序列尾</li> 
  133.      * <li>將另一序列剩下的所有元素直接複製到合併序列尾</li> 
  134.      * </ul> 
  135.      * 演算法參考:<a href="http://www.cnitblog.com/intrl/" mce_href="http://www.cnitblog.com/intrl/">Java部落</a> 
  136.      *  
  137.      * @param numbers 
  138.      */
  139. publicstaticvoid mergeSort(int[] numbers, int left, int right) {  
  140. int t = 1;// 每組元素個數
  141. int size = right - left + 1;  
  142. while (t < size) {  
  143. int s = t;// 本次迴圈每組元素個數
  144.             t = 2 * s;  
  145. int i = left;  
  146. while (i + (t - 1) < size) {  
  147.                 merge(numbers, i, i + (s - 1), i + (t - 1));  
  148.                 i += t;  
  149.             }  
  150. if (i + (s - 1) < right)  
  151.                 merge(numbers, i, i + (s - 1), right);  
  152.         }  
  153.     }  
  154. /** 
  155.      * 歸併演算法實現 
  156.      *  
  157.      * @param data 
  158.      * @param p 
  159.      * @param q 
  160.      * @param r 
  161.      */
  162. privatestaticvoid merge(int[] data, int p, int q, int r) {  
  163. int[] B = newint[data.length];  
  164. int s = p;  
  165. int t = q + 1;  
  166. int k = p;  
  167. while (s <= q && t <= r) {  
  168. if (data[s] <= data[t]) {  
  169.                 B[k] = data[s];  
  170.                 s++;  
  171.             } else {  
  172.                 B[k] = data[t];  
  173.                 t++;  
  174.             }  
  175.             k++;  
  176.         }  
  177. if (s == q + 1)  
  178.             B[k++] = data[t++];  
  179. else
  180.             B[k++] = data[s++];  
  181. for (int i = p; i <= r; i++)  
  182.             data[i] = B[i];  
  183.     }  
  184. }  

數字排序演算法通常用來作為演算法入門課程的基本內容,在實際應用(尤其是普通商業軟體)中使用的頻率較低,但是通過排序演算法的實現,可以深入瞭解計算機語言的特點,可以以此作為學習各種程式語言的基礎。

分享到: