直接插入、冒泡、快速、简单选择、堆、归并排序算法

一、直接插入

第i趟直接插入排序的操作为:在含有i-1个记录的有序子序列r[1...i-1]中插入一个记录r[i]后,变成含有i个记录的有序子序列[1..i];为了避免数组下标出界,在r[0]处设置监视哨。
如第一趟排序为:将序列中的第1个记录看成是一个有序的子序列,然后从第2个记录起逐个进行插入,直到整个序列变成按关键字非递减有序序列为止。下面是第一趟排序的图:

[java]  view plain  copy
  1.  public void insertionSort( int[] arr) {  
  2.        int guide = 0;  
  3.        for ( int i = 1; i < arr. length; i++) {  
  4.             if ( arr[ i] < arr[ i - 1]) {  
  5.                  guide = arr[ i];  
  6.                  arr[ i] = arr[ i - 1];  
  7.                  int j = i - 1;  
  8.                  while ( j >= 0 && guide < arr[ j]) {  
  9.                        arr[ j + 1] = arr[ j];  
  10.                        j--;  
  11.                 }  
  12.                  arr[ j+1] = guide;  
  13.            }  
  14.       }  
  15. }  

二、冒泡排序

第i趟冒泡排序是从r[1]到r[n-i+1]依次比较相邻两个记录的关键字,并在“逆序”时交换相邻记录,其结果是这n-i+1个记录中关键字最大的记录被交换到第n-i+1的位置上。下面为第一趟排序的示意图:

[java]  view plain  copy
  1.  public void bubbleSort( int[] arr) {  
  2.        for ( int i = arr. length - 1; i >= 1; i--) {  
  3.             for ( int j = 1; j <= i; j++) {  
  4.                  if ( arr[ j - 1] > arr[ j]) {  
  5.                        int temp = arr[ j];  
  6.                        arr[ j] = arr[ j - 1];  
  7.                        arr[ j - 1] = temp;  
  8.                 }  
  9.            }  
  10.       }  
  11. }  

三、快速排序

它的一趟操作为:附设两个指针low和high,它们的初值分别为low和high,设枢轴记录的关键字为pivotkey(可以直接取数组的中间 值和下标),则首先从high所指位置起向前搜索找到第一个关键字小于pivotkey的记录和枢轴记录互相交换,然后从low所指位置起向后搜索,找到第一个关键字大于pivotkey的记录和枢轴记录互相交换,重复这两步直至low=high为止。第一趟的示意图如下:

[java]  view plain  copy
  1.  public void quickSort( int[] arr, int low, int high) {  
  2.        if ( arr. length < 2 || low >= high) {  
  3.             return;  
  4.       }  
  5.   
  6.        if ( low < high) {  
  7.             int pivotloc = partition( arr, low, high);  
  8.            quickSort( arr, low, pivotloc - 1);  
  9.            quickSort( arr, pivotloc + 1, high);  
  10.       }  
  11. }  
  12.   
  13.  public int partition (int [] arr , int low, int high) {  
  14.        if ( arr. length < 2) {  
  15.             return 0;  
  16.       }  
  17.   
  18.        int pivotkey;  
  19.        pivotkey = arr[ low];  
  20.        while ( low < high) {  
  21.             while ( low < high && arr[ high] >= pivotkey) {  
  22.                  high--;  
  23.            }  
  24.             arr[ low] = arr[ high];  
  25.             while ( low < high && arr[ low] <= pivotkey) {  
  26.                  low++;  
  27.            }  
  28.             arr[ high] = arr[ low];  
  29.       }  
  30.        arr[ low] = pivotkey;  
  31.        return low;  
  32. }  

四、简单选择

一趟简单选择排序的操作为:通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之。(i指趟数,n指数组长度)。完整的例子如下图:


[java]  view plain  copy
  1.  public void selectionSort( int[] arr) {  
  2.        for ( int i = 0; i < arr. length - 1; i++) {  
  3.             int minIndex = i;  
  4.             for ( int j = i + 1; j < arr. length; j++) {  
  5.                  if ( arr[ j] < arr[ minIndex]) {  
  6.                        minIndex = j;  
  7.                 }  
  8.            }  
  9.   
  10.             if ( i != minIndex) {  
  11.                  int temp = arr[ minIndex];  
  12.                  arr[ minIndex] = arr[ i];  
  13.                  arr[ i] = temp;  
  14.            }  
  15.       }  
  16. }  


五、堆排序

堆是指:完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。
堆排序是指:在输出堆顶的最小(大)值后,使得剩余n-1个元素的序列重新建成一个小(大)顶堆,则得到n个元素中的次小( 大)值。如此反复执行,便能得到一个有序序列。
算法的大致过程(大顶堆为例):输出堆顶的元素后,以堆中最后一个元素替代之。此时根结点的左、右子树均为堆,则仅需自上而下进行调整即可。首先以堆顶元素和其左、右子树根结点的值比较之,将较大的根结点的值与堆顶交换;这时被交换的结点的树的堆结构被破坏,需再将该结点与其左、右子树根结点的值比较之,将较大的根结点的值与它交换,以此类推重新建成堆。

自己根据书本的内容介绍用Java语言实现:
[java]  view plain  copy
  1.  public void heapSort( int[] arr) {  
  2.        for ( int i = arr. length / 2; i > 0; -- i) {  
  3.            heapAdjust( arr, i, arr. length);  
  4.       }  
  5.        for ( int i = arr. length; i > 1; -- i) {  
  6.            swap( arr, 1 - 1, i - 1); //逻辑堆的下标和实际数组的下标错开1个单位,即堆顶与堆末交换  
  7.            heapAdjust( arr, 1, i - 1);  
  8.       }  
  9. }  
  10.  /** 
  11.  * 此方法是根据堆的逻辑来处理数组的,而堆的最小值为1,最大值应该是要处理的数组的长度length; 
  12.  * 然而数组的下标最小为0,最大为length -1,所以方法中将逻辑堆的下标和实际数组的下标错开1个单位; 
  13.  * 因此 arr数组取值时,都要将堆计算时的下标数减1 
  14.  * @param arr 要处理成符合大顶堆的数组 
  15.  * @param s 要处理处的开始下标 
  16.  * @param m 结束下标 
  17.  */  
  18.  public void heapAdjust( int[] arr, int s, int m) {  
  19.        int rc = arr[ s-1];  
  20.        for ( int j = 2 * s; j <= m; j *= 2) {  
  21.             if ( j < m && arr[ j-1] < arr[ j ]) {  
  22.                 ++ j;  
  23.            }  
  24.             if ( rc >= arr[ j-1]) {  
  25.                  break;  
  26.            }  
  27.             arr[ s-1] = arr[ j-1];  
  28.             s = j;  
  29.       }  
  30.        arr[ s-1] = rc;  
  31. }  

下面根据网上的JavaScript代码写的:
[java]  view plain  copy
  1.  int len;  
  2.   
  3.  public void buildMaxHeap( int[] arr) {   // create a big heap  
  4.     len = arr. length;  
  5.     int i = new Double(Math. floor( len/2)).intValue();  
  6.     System. out.println( "buildMaxHeap's i=" + i );  
  7.     for (; i >= 0; i--) {  
  8.         heapify( arr, i);  
  9.     }  
  10. }  
  11.   
  12.  public void heapify( int[] arr, int i) {     // adjust the heap  
  13.     int left = 2 * i + 1,  
  14.         right = 2 * i + 2,  
  15.         largest = i;  
  16.   
  17.     if ( left < len && arr[ left] > arr[ largest]) {  
  18.         largest = left;  
  19.     }  
  20.   
  21.     if ( right < len && arr[ right] > arr[ largest]) {  
  22.         largest = right;  
  23.     }  
  24.   
  25.     if ( largest != i) {  
  26.         swap( arr, i, largest);  
  27.         heapify( arr, largest);  
  28.     }  
  29. }  
  30.   
  31.  public void swap( int[] arr, int i, int j) {  
  32.     int temp = arr[ i];  
  33.     arr[ i] = arr[ j];  
  34.     arr[ j] = temp;  
  35. }  
  36.   
  37.  public int[] heapSort( int[] arr) {  
  38.     buildMaxHeap( arr);  
  39.   
  40.     for ( int i = arr. length-1; i > 0; i--) {  
  41.         swap( arr, 0, i);  
  42.         len--;  
  43.         heapify( arr, 0);  
  44.     }  
  45.     return arr;  
  46. }  

六、归并排序

归并排序的理念是:假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再再两两归并,....如此重复下去即可。


[java]  view plain  copy
  1. public int [] mergeSort (int [] arr ) {//sort a array  
  2.             int len = arr. length;  
  3.             if ( len < 2) {  
  4.                  return arr;  
  5.            }  
  6.   
  7.             int middle = len / 2;  
  8.             int[] left = Arrays. copyOfRange( arr, 0, middle);  
  9.             int[] right = Arrays. copyOfRange( arr, middle, len);  
  10.             return merge( mergeSort( left), mergeSort (right ));  
  11.      }  
  12.   
  13.       public int[] merge( int[] left, int[] right) { //merge two regular arrays into one regular array  
  14.             int j, i, k = 0;  
  15.             int m = left. length;  
  16.             int n = right. length;  
  17.             int result[] = new int[ left. length + right. length] ;  
  18.             for ( j = 0, i = 0; i < m && j < n; k++) {  
  19.                  if ( left[ i] < right[ j]) {  
  20.                       result[ k] = left[ i];  
  21.                       i++;  
  22.                 } else {  
  23.                       result[ k] = right[ j];  
  24.                       j++;  
  25.                 }  
  26.            }  
  27.             while ( i < m) {  
  28.                  result[ k++] = left[ i++];  
  29.            }  
  30.             while ( j < n) {  
  31.                  result[ k++] = right[ j++];  
  32.            }  
  33.             return result;  
  34.      }  

猜你喜欢

转载自blog.csdn.net/qq_32868167/article/details/77937623