算法設計分析(二分歸並排序)


1. 問題

二分歸並排序:對n個不同的數構成的數組A[1..n]進行排序,其中n=2^k

2. 解析

二分歸並排序采用了分治的思想,將序列不斷划分成左右兩個序列,然后依次將小序列進行排序,然后歸並到大序列中。

3. 設計

void Mergesort(int l,int r)

{

    int mid = (l + r) >> 1;

    if(r - l + 1 <= 1)  // 如果序列長度<=1的話那么這個序列必然是有序的

    {

        return;

    }

    else if(r - l + 1 == 2) // 如果這個序列的長度 == 2 那么我們可以手動對這個序列進行排序

    {

        if(arr[r] < arr[l])

        {

            int t;

            t = arr[r];

            arr[r] = arr[l];

            arr[l] = t;

        }

    }

    else

    {

        Mergesort(l , mid);     

        Mergesort(mid + 1,  r); 

        // 當序列長度 > 2時,我們把序列分成兩塊,分別對序列的左子序列,和右子序列進行排序

        // 左右子序列排好序之后,我們需要把左右兩個子序列歸並成為一個有序序列

        int s1 = l , s2 = mid + 1;

        int s = l;

        while(s1 <= mid && s2 <= r) // 每次只取兩個子序列中最小,這樣來將兩個子序列歸並到一起

        {

            if(arr[s1] < arr[s2]) tmp[s++] = arr[s1++];

            else tmp[s++] = arr[s2++];

        }

        while(s1 <= mid) tmp[s++] = arr[s1++];

        while(s2 <= r) tmp[s++] = arr[s2++];

        for(int i = l ; i <= r; ++ i) arr[i] = tmp[i]; // 把排序好的tmp數組賦值給arr

    }

}

 

4. 分析

時間復雜度:O(nlogn)

解析:每次都將數列分成左右兩個序列,每次歸並的時候需要將元素復制到tmp數組中。又因為最多歸並logn層,每層所需的時間是n。

空間復雜度:O(n)

解析:在歸並的時候需要將元素賦值到tmp數組,因此需要另外開一個tmp數組,這個數組的大小 >= 存有數據的數組的大小。

4. 完整代碼

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #include<math.h>
 5 #include<algorithm>
 6 #include<time.h>
 7 
 8 const int maxn = 1e5 + 100;    //
 9 
10 int arr[maxn] ,tmp[maxn];  // arr數組用於存儲排序前和排序后的序列,tmp數組用於在二分歸並排序的過程中使用
11 int n; // n 代表序列的長度
12 void Mergesort(int l,int r)
13 {
14     int mid = (l + r) >> 1;
15     if(r - l + 1 <= 1)  // 如果序列長度<=1的話那么這個序列必然是有序的
16     {
17         return;
18     }
19     else if(r - l + 1 == 2) // 如果這個序列的長度 == 2 那么我們可以手動對這個序列進行排序
20     {
21         if(arr[r] < arr[l])
22         {
23             int t;
24             t = arr[r];
25             arr[r] = arr[l];
26             arr[l] = t;
27         }
28     }
29     else
30     {
31         Mergesort(l , mid);     
32         Mergesort(mid + 1,  r); 
33         // 當序列長度 > 2時,我們把序列分成兩塊,分別對序列的左子序列,和右子序列進行排序
34         // 左右子序列排好序之后,我們需要把左右兩個子序列歸並成為一個有序序列
35         int s1 = l , s2 = mid + 1;
36         int s = l;
37         while(s1 <= mid && s2 <= r) // 每次只取兩個子序列中最小,這樣來將兩個子序列歸並到一起
38         {
39             if(arr[s1] < arr[s2]) tmp[s++] = arr[s1++];
40             else tmp[s++] = arr[s2++];
41         }
42         while(s1 <= mid) tmp[s++] = arr[s1++];
43         while(s2 <= r) tmp[s++] = arr[s2++];
44         for(int i = l ; i <= r; ++ i) arr[i] = tmp[i]; // 把排序好的tmp數組賦值給arr
45     }
46 }
47 
48 
49 int main()
50 {
51     srand(time(NULL));
52     scanf("%d",&n);
53     for(int i = 1 ; i <= n ; ++ i)
54     {
55         arr[i] = rand()%100 + 1; // 通過隨機數生成數組元素
56     }
57     Mergesort(1 , n);
58     for(int i = 1 ; i <= n ; ++ i)
59     {
60         printf("%d ",arr[i]);
61     }
62     printf("\n");
63     return 0;
64 }
二分歸並排序

 


免責聲明!

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



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