圖解排序演算法(四)之歸併排序

來源:互聯網
上載者:User

標籤:經典的   最好   nlog   技術   private   ima   col   val   問題   

基本思想

  歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該演算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然後遞迴求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。

分而治之

   可以看到這種結構很像一棵完全二叉樹,本文的歸併排序我們採用遞迴去實現(也可採用迭代的方式去實現)。分階段可以理解為就是遞迴拆分子序列的過程,遞迴深度為log2n。

合并相鄰有序子序列

  再來看看治階段,我們需要將兩個已經有序的子序列合并成一個有序序列,比如中的最後一次合并,要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子序列,合并為最終序列[1,2,3,4,5,6,7,8],來看下實現步驟。

代碼實現
import java.util.Arrays;/** * Created by chengxiao on 2016/12/8. */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中            temp[t++] = arr[i++];        }        while(j<=right){//將右序列剩餘元素填充進temp中            temp[t++] = arr[j++];        }        t = 0;        //將temp中的元素全部拷貝到原數組中        while(left <= right){            arr[left++] = temp[t++];        }    }}

單向鏈表的歸併排序:

ListNode *sortList(ListNode *head) {        if(head==nullptr||head->next==nullptr)            return head;        //採用快慢指標找到中間節點        ListNode *fast=head,*slow=head;           while(fast!=nullptr&&fast->next!=nullptr&&fast->next->next!=nullptr){            fast=fast->next->next;            slow=slow->next;        }        //斷開        fast=slow;        slow=slow->next;        fast->next=nullptr;        fast=sortList(head);        slow=sortList(slow);        return merge(fast,slow);    }         ListNode* merge(ListNode* sub1,ListNode* sub2){        if(sub1==nullptr)return sub2;        if(sub2==nullptr)return sub1;                ListNode* head=nullptr;        if(sub1->val<sub2->val){            head=sub1;            sub1=sub1->next;        }        else{            head=sub2;            sub2=sub2->next;        }        ListNode* p=head;        while(sub1!=nullptr&&sub2!=nullptr){            if(sub1->val<sub2->val){                p->next=sub1;                sub1=sub1->next;            }            else{                p->next=sub2;                sub2=sub2->next;            }            p=p->next;        }        if(sub1!=nullptr)            p->next=sub1;        if(sub2!=nullptr)            p->next=sub2;        return head;    }
最後

  歸併排序是穩定排序,它也是一種十分高效的排序,能利用完全二叉樹特性的排序一般效能都不會太差。java中Arrays.sort()採用了一種名為TimSort的排序演算法,就是歸併排序的最佳化版本。從上文的圖中可看出,每次合併作業的平均時間複雜度為O(n),而完全二叉樹的深度為|log2n|。總的平均時間複雜度為O(nlogn)。而且,歸併排序的最好,最壞,平均時間複雜度均為O(nlogn)。

圖解排序演算法(四)之歸併排序

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.