Java实现几种常见排序方法

日常操作中常见的排序方法有:冒泡排序、快速排序、选择排序、插入排序、希尔排序,甚至还有基数排序、鸡尾酒排序、桶排序、鸽巢排序、归并排序等。

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

快速排序使用分治法策略来把一个序列分为两个子序列。

  1. /**  
  2.  * 快速排序<br/>  
  3.  * <ul>  
  4.  * <li>从数列中挑出一个元素,称为“基准”</li>  
  5.  * <li>重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,  
  6.  * 该基准是它的最后位置。这个称为分割(partition)操作。</li>  
  7.  * <li>递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。</li>  
  8.  * </ul>  
  9.  *   
  10.  * @param numbers  
  11.  * @param start  
  12.  * @param end  
  13.  */   
  14. public   static   void  quickSort( int [] numbers,  int  start,  int  end) {  
  15.     if  (start < end) {  
  16.         int  base = numbers[start];  // 选定的基准值(第一个数值作为基准值)   
  17.         int  temp;  // 记录临时中间值   
  18.         int  i = start, j = end;  
  19.         do  {  
  20.             while  ((numbers[i] < base) && (i < end))  
  21.                 i++;  
  22.             while  ((numbers[j] > base) && (j > start))  
  23.                 j--;  
  24.             if  (i <= j) {  
  25.                 temp = numbers[i];  
  26.                 numbers[i] = numbers[j];  
  27.                 numbers[j] = temp;  
  28.                 i++;  
  29.                 j--;  
  30.             }  
  31.         } while  (i <= j);  
  32.         if  (start < j)  
  33.             quickSort(numbers, start, j);  
  34.         if  (end > i)  
  35.             quickSort(numbers, i, end);  
  36.     }  
  37. }  

选择排序是一种简单直观的排序方法,每次寻找序列中的最小值,然后放在最末尾的位置。

  1. /**  
  2.  * 选择排序<br/>  
  3.  * <ul>  
  4.  * <li>在未排序序列中找到最小元素,存放到排序序列的起始位置</li>  
  5.  * <li>再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾。</li>  
  6.  * <li>以此类推,直到所有元素均排序完毕。</li>  
  7.  * </ul>  
  8.  *   
  9.  * @param numbers  
  10.  */   
  11. public   static   void  selectSort( int [] numbers) {  
  12.     int  size = numbers.length, temp;  
  13.     for  ( int  i =  0 ; i < size; i++) {  
  14.         int  k = i;  
  15.         for  ( int  j = size -  1 ; j >i; j--)  {  
  16.             if  (numbers[j] < numbers[k])  k = j;  
  17.         }  
  18.         temp = numbers[i];  
  19.         numbers[i] = numbers[k];  
  20.         numbers[k] = temp;  
  21.     }  

 

插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。其具体步骤参见代码及注释。

  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. public   static   void  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. }  

归并排序是建立在归并操作上的一种有效的排序算法,归并是指将两个已经排序的序列合并成一个序列的操作。参考代码如下:

  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. public   static   void  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. private   static   void  merge( int [] data,  int  p,  int  q,  int  r) {  
  38.     int [] B =  new   int [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类,代码

  1. /**  
  2.  * BubbleSort.class  
  3.  */   
  4. package  test.sort;  
  5. import  java.util.Random;  
  6. /**  
  7.  * Java实现的排序类  
  8.  *   
  9.  * @author cyq  
  10.  *   
  11.  */   
  12. public   class  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.     public   static   void  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.     public   static   void  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.     public   static   void  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.     public   static   void  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.     public   static   void  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.     private   static   void  merge( int [] data,  int  p,  int  q,  int  r) {  
  163.         int [] B =  new   int [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.   
  185. }  

数字排序算法通常用来作为算法入门课程的基本内容,在实际应用(尤其是普通商业软件)中使用的频率较低,但是通过排序算法的实现,可以深入了解计算机语言的特点,可以以此作为学习各种编程语言的基础。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章