zoukankan      html  css  js  c++  java
  • 算法设计分析(二分归并排序)

    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("
    ");
    63     return 0;
    64 }
    二分归并排序
  • 相关阅读:
    标识类型模式
    脏检查和快照的故事
    Hibernate入门案例及增删改查
    Oracle函数解析
    Oracle基础及三层分页查询
    java解析xml文档(dom)
    TCP和UDP的聊天
    java线程同步
    试题分析(第三套)
    java线程的简单实现及方法
  • 原文地址:https://www.cnblogs.com/DreamACMer/p/12555599.html
Copyright © 2011-2022 走看看