zoukankan      html  css  js  c++  java
  • 数据结构与算法复习(三)归并排序

    归并排序的思想是:将两个有序的子序列通过归并得到一个大的子序列实现序列有序化
    算法实现过程如下:
    1、将数组划分为一个个最小的子序列,即每个子序列只有一个元素
    2、将最小的子序列两两归并得到大的子序列
    3、递归执行步骤2,直到归并得到最大的序列,即有序的整个序列

    比如如下序列:
    16 9 8 20 7 9 6 5
    先将序列递归划分成最小的子序列
    16 9 8 20 | 7 9 6 5
    16 9 | 8 20 | 7 9 | 6 5
    16 | 9 | 8 | 20 | 7 | 9 | 6 | 5
    将子序列依次归并得到最终有序序列,比如序列16 | 9归并后为9 16
    9 16 | 8 20 | 7 9 | 5 6
    8 9 16 20 | 5 6 7 9
    5 6 7 8 9 9 16 20

    归并排序是一种稳定的排序算法。
    空间复杂度:归并排序需要一个与原序列等长的空间作为归并时的缓存用,所以空间复杂度为O(n);

    时间复杂度:归并排序的时间主要花费在归并操作上,因为是对有序的子序列归并,只需要扫描一遍子序列元素,
    因此一次归并操作花费的时间是O(n),归并排序将序列划分成log2n种子序列长度不同的序列,因此需要归并操作
    log2n次,所以时间复杂度是O(nlog2n),但是每次归并完成后,需要将归并后的元素拷贝回原序列,因此通常
    花费的时间会比快速排序多。

    针对已经有序的排序,归并排序可以在归并时对比两子序列的最小元素和最大元素,如果已经有序,则跳过归并
    过程,这样时间复杂度就为O(n)

    算法代码实现如下:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 /* 用时间做种子产生随机数 */
     5 #include <time.h>
     6 
     7 #define MAXLEN 50
     8 static int tmp[MAXLEN];
     9 
    10 void ms(int A[], int left, int right)
    11 {
    12     /*
    13      * left是数组左下标
    14      * right是数组右下标
    15      */
    16     int mid, l, r, k;
    17 
    18     if (A == NULL || left >= right) {
    19         return;
    20     }
    21 
    22     mid = (left + right) / 2;
    23     ms(A, left, mid);
    24     ms(A, mid + 1, right);
    25 
    26     l = left;
    27     r = mid + 1;
    28     k = 0;
    29     while (l <= mid && r <= right) {
    30         if (A[l] <= A[r]) {
    31             tmp[k++] = A[l++];
    32         }
    33         else {
    34             tmp[k++] = A[r++];
    35         }
    36     }
    37 
    38     while (l <= mid) {
    39         tmp[k++] = A[l++];
    40     }
    41 
    42     while (r <= right) {
    43         tmp[k++] = A[r++];
    44     }
    45 
    46     /* 将有序的tmp拷贝到数组A中 */
    47     k = 0;
    48     for (l = left; l <= right; l++) {
    49         A[l] = tmp[k++];
    50     }
    51 
    52 }
    53 
    54 static void printA(int A[], int len)
    55 {
    56     int i;
    57 
    58     for (i = 0; i < len; i++) {
    59         printf("%d ", A[i]);
    60     }
    61     printf("
    ");
    62 }
    63 
    64 int main(int argc, char **argv){
    65     int i, res, len;
    66     int A[50]; // = {-1,6,2,3,9,19};
    67 
    68     srand((int)time(NULL));
    69     len = rand() % 51; //51;
    70     printf("len is %d.
    ", len);
    71 
    72     srand((int)(time(NULL) + len));
    73     for (i = 0; i < len; i++) {
    74         A[i] = rand() % 100;
    75     }
    76 
    77     printf("before sort :
    ");
    78     printA(A, len);
    79 
    80     ms(A, 0, len - 1);
    81 
    82     printf("after sort :
    ");
    83     printA(A, len);
    84 
    85     return 0;
    86 }
  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/lztutumo/p/13537761.html
Copyright © 2011-2022 走看看