【排序】三種經典高效排序算法


(一)快速排序

第一步:選擇軸值,選擇策略

第二步:將待排序序列划分為兩個子序列L和R,使得L中的所有記錄都小於等於軸值,而R中的所有記錄都大於軸值,也就是關鍵的划分算法。

第三步:對子序列L和R遞歸快速排序。

class Solution {
    //快速排序
    public int[] sortArray(int[] nums) {
        if(nums==null ||nums.length<2)
            return nums;
        quickSort(nums,0,nums.length-1);
        return nums;
    }
    public void quickSort(int[] nums,int low,int high){
        if(low>=high)
            return;
        int index=partition(nums,low,high);
        quickSort(nums,low,index-1);
        quickSort(nums,index+1,high);
    }
    public int partition(int[] nums,int low,int high){
        int i=low,j=high;
        int temp=nums[low];  //軸值選擇最左邊的一個
        while(i<j){
            while(i<j && nums[j]>=temp)
                j--;
            if(i<j){
                nums[i]=nums[j];
                i++;
            }
            while(i<j && nums[i]<temp)
                i++;
            if(i<j){
                nums[j]=nums[i];
                j--;
            }
        }
        nums[i]=temp;
        return i;
    }
}

(二)歸並排序

二路歸並:

class Solution {
    //歸並排序
    public int[] sortArray(int[] nums) {
        if(nums==null && nums.length<2)
            return nums;
        mergeSort(nums,0,nums.length-1);
        return nums;
    }
    public void mergeSort(int[] nums,int low,int high){
        if(low>=high)
            return ;
        int mid=low+(high-low)/2;
        mergeSort(nums,low,mid);
        mergeSort(nums,mid+1,high);
        merge(nums,low,mid,high);
    }
    public void merge(int[] nums, int low,int mid,int high){
        int[] temp=new int[high-low+1];
        int i=low,j=mid+1,k=0;
        while(i<=mid && j<=high){
            if(nums[i]<=nums[j])
                temp[k++]=nums[i++];
            else
                temp[k++]=nums[j++];
        }
        while(i<=mid)
            temp[k++]=nums[i++];
        while(j<=high)
            temp[k++]=nums[j++];
        
        for(int t=0;t<temp.length;t++)
            nums[t+low]=temp[t];
    }
}

(三)堆排序

堆:

  一個關鍵字序列{K0,K1,…,Kn-1},當滿足條件(1)或(2)時就稱為堆。

(1) Ki ≤K2i +1 或 (2) Ki ≥K2i+1

​ Ki ≤K2i+2      Ki ≥K2i+2

  滿足(1)的序列為最小堆(小頂堆)。

  滿足(2)的序列為最大堆(大頂堆)。

篩選法:

堆排序:

class Solution {
    //堆排序,O(nlogn)
    public int[] sortArray(int[] nums) {
        buildHeap(nums);  //建立初始堆
        for(int i=nums.length-1;i>=0;i--){
            //交換
            int temp=nums[0];
            nums[0]=nums[i];
            nums[i]=temp;

            //重新構建大頂堆,0下篩
            heapAdjustDown(nums,i,0);
        }

        return nums;
    }

    public void buildHeap(int[] nums){  //建堆
        for(int i=nums.length/2-1;i>=0;i--)
            heapAdjustDown(nums,nums.length,i);
    }
	
    //下篩算法,時間復雜度O(nlogn)
    public void heapAdjustDown(int[] nums, int n, int h){  //篩選算法,下篩,將nums[h]拉下來
        int i=h,temp=nums[h];  //標記父結點
        int j=2*i+1; //左孩子

        while(j<n){
            if(j<n-1 && nums[j+1]>nums[j])
                j=j+1;  //j為孩子中的較大者
            
            if(temp>nums[j])  //滿足大頂堆
                break;
            else{
                nums[i]=nums[j];
                i=j;
                j=2*i+1;
            }
        }
        nums[i]=temp;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM