1. 程式人生 > >七大經典排序(Java版)

七大經典排序(Java版)

AR The 插入 構建 選擇 n個元素 升序 基準 互換

.

冒泡排序: 通過相鄰的兩個數的比較, 根據需要決定是否將兩個數互換位置, 然後將比較往前(或往後)推進. 最簡單的排序算法,直接上代碼。    技術分享圖片
for(i=0;i<length-1;i++)
    for(j=i+1;j<length;j++)
    if(arrayVal[i]>arrayVal[j])
     {
             //置換位置
             temp=arrayVal[i];
             arrayVal[i]=arrayVal[j];
             arrayVal[j]
=temp; } }
View Code 選擇排序: "選擇排序"就是第0個逐步和後面全部的比,比完0位置就得到最小的數,緊接著再從1位置對比後面的元素,以此類推,逐步得到從小到大的值.   技術分享圖片
for(int i = 0; i < arr.length - 1; i++) {        int k = i;    for(int j = k + 1; j < arr.length; j++){        if( arr[j] < arr[k]){        k =j;      }        //在內層循環結束,也就是找到本輪循環的最小的數以後,再進行交換    if( i != k) {     int temp= arr[i];    arr[i] = arr[k];    arr[k] = temp;    }
View Code 插入排序: 首先對數組的前兩個數據進行從小到大的排序。 接著將第三個數據與排好序的兩個數據比較,將第三個數據插入合適的位置。 然後將第四個數據插入到已排好序的前3個數據中。 ....
// 第1個數肯定是有序的,從第2個數開始遍歷,依次插入有序序列
     
    public  static void insertionSort(int[] a){
  
          for(int i = 1 ; i < a.length; i++){
              
              
int temp = a[i]; int j = i - 1; while( j >= 0 && temp < a[j]){ a[j+1] = a[j]; j--; } a[j+1] = temp; }

Shell排序算法:(希爾排序、縮小增量排序): 

  Shell排序是基於插入排序的思想。 1.將有n個元素的數組分成n/2個數字序列,第1個數據和第n/2+1個數據為一對,... 2.一次循環使每一個序列對排好順序。 3.然後,變為n/4個序列,在次排序。 4.直到序列變為1個。 技術分享圖片
   //希爾排序  
     public static void shellSort(int a[]){
          
          for(int r = a.length/2 ; r >= 1; r/=2 ){
              
              for(int i = r; i < a.length ; i++){
                   
                   int temp = a[i];
                   int j = i - r;
                   
                   while(j >= 0 && temp < a[j]){
                        a[j+r] = a[j];
                        j -= r;
                   }
                   
                   a[j+r] = temp;
              }
          }
     }

快速排序算法

  1.在待排序的元素任取一個元素作為基準(通常選第一個元素,但最的選擇方法是從待排序元素中隨機選取一個作為基準),稱為基準元素; 2.將待排序的元素進行分區,比基準元素大的元素放在它的右邊,比其小的放在它的左邊; 3.對左右兩個分區重復以上步驟直到所有元素都是有序的。
public static void quickSort3(int arr[],int _left,int _right){
          
        int left = _left;
        int right = _right;
        int temp = 0;
       
        if(left <= right){   //待排序的元素至少有兩個的情況
          
            temp = arr[left];  //待排序的第一個元素作為基準元素
            while(left != right){   //從左右兩邊交替掃描,直到left = right
                while(right > left && arr[right] >= temp){
                   right --;        //從右往左掃描,找到第一個比基準元素小的元素
                }
                arr[left] = arr[right]; 
                while(left < right && arr[left] <= temp){
                   left ++;         //從左往右掃描,找到第一個比基準元素大的元素
                }
               
                arr[right] = arr[left]; 
            }
            arr[right] = temp;    //基準元素歸位
            quickSort3(arr,_left,left-1);  //對基準元素左邊的元素進行遞歸排序
            quickSort3(arr, right+1,_right);  //對基準元素右邊的進行遞歸排序
           
        }       
    }

堆排序算法

  堆排序是利用堆這種數據結構而設計的一種排序算法,堆排序是一種選擇排序,它的最壞,最好,平均時間復雜度均為O(nlogn),它也是不穩定排序。首先簡單了解下堆結構。 堆: 堆是具有以下性質的完全二叉樹: 每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆。

   技術分享圖片

  堆排序的基本思想:將待排序序列構造成一個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然後將剩余n-1個元素重新構造成一個堆,這樣會得到n個元素的次小值。如此反復執行,便能得到一個有序序列了。

  堆排序的基本步驟:

    1.構造初始堆。將給定無序序列構造成一個大頂堆(一般升序采用大頂堆,降序采用小頂堆)。

    2.將堆頂元素與末尾元素進行交換,使末尾元素最大。然後繼續調整堆,再將堆頂元素與末尾元素交換,得到第二大元素。如此反復進行交換、重建、交換。

   

public class HeapSort {
     
    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
   
   
    public static void sort(int []arr){
        //1.構建大頂堆
        for(int i=arr.length/2-1;i>=0;i--){
            adjustHeap(arr,i,arr.length);
        }
       
        for(int j=arr.length-1;j>0;j--){
            swap(arr,0,j);
            adjustHeap(arr,0,j);
        }
    }
    
    // 調整大頂堆
    public static void adjustHeap(int []arr,int i,int length){
        int temp = arr[i];
        for(int k=i*2+1;k<length;k=k*2+1){
            if(k+1<length && arr[k]<arr[k+1]){
                k++;
            }
            if(arr[k] >temp){//如果子節點大於父節點,將子節點值賦給父節點
                arr[i] = arr[k];
                i = k;
            }else{
                break;
            }
        }
        arr[i] = temp;
    }
    //交換元素
    public static void swap(int []arr,int a ,int b){
        int temp=arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}
歸並排序   歸並排序(MERGE-SORT)是利用歸並的思想實現的排序方法,該算法采用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然後遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。   
public class MergeSort {

    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void sort(int []arr){
        int []temp = new int[arr.length];//在排序前,先建好一個長度等於原數組長度的臨時數組,避免遞歸中頻繁開辟空間
        sort(arr,0,arr.length-1,temp);
    }

    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左邊歸並排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右邊歸並排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//將兩個有序子數組合並操作
        }
    }

    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;
        int j = mid+1;
        int t = 0;
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){
            temp[t++] = arr[i++];
        }
        while(j<=right){
            temp[t++] = arr[j++];
        }
        t = 0;
        //將temp中的元素全部拷貝到原數組中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}

各個排序算法比較:

排序算法 平均速度 最壞情況 是否穩定
冒泡排序 O( n^2) O( n^2) 穩定
快速排序 O(nlogn) O( n^2) 不穩定
選擇排序 O( n^2) O( n^2) 不穩定
插入排序 O( n^2) O( n^2) 穩定
堆排序 O(nlogn) O(nlogn) 不穩定
Shell排序 O( n^(3/2) ) O( n^2) 不穩定
合並排序 O(nlogn) O(nlogn) 穩定

七大經典排序(Java版)