• 归并排序,冯诺依曼首次提出。分为递归实现、非递归实现


    一、实现思想

      1、将数组分成一个个小序列  (当然在一开始这些小序列都是一个元素)

      2、将相邻两个小序列合并起来(当然在合并的时候排好序)

    二、实现图例

      1、递归实现

      2、非递归实现(循环实现)

    三、代码实现

    (递归和非递归地合并代码都是一样的,即merge函数都是一样)

      1、递归代码实现

     1 #include <stdio.h>
     2 int data[] = {8, 3, 2, 6, 7, 1, 5, 4};
     3 int length = 8;
     4 //将两个序列合并
     5 void merge(int first1, int last1, int last2)
     6 {
     7     int *temp = new int[length]; //数组temp作为合并的辅助空间,注意这个数组和原来的数组是一样大小的,为了方便
     8     int i = first1;              //左序列第一个元素下标
     9     int j = last1 + 1;           //右序列第一个元素下标
    10     int k = first1;              //左序列第一个元素下标,用于记录合并后的初始位置(将temp复制到data上)
    11     while (i <= last1 && j <= last2)
    12     {
    13         if (data[i] <= data[j])
    14             temp[k++] = data[i++]; //升序排序,将小的放前面。如要修改,改变一下符号即可。
    15         else
    16             temp[k++] = data[j++];
    17     }
    18     while (i <= last1)         //做一些收尾工作,比如只剩下一边有几个(当然了,这几个必定是有序的了)
    19         temp[k++] = data[i++]; //注意这里的++也很有必要,因为有可能一边的序列有好几个剩下的
    20     while (j <= last2)
    21         temp[k++] = data[j++];
    22     for (i = first1; i <= last2; i++)
    23         data[i] = temp[i];
    24     delete[] temp;
    25 }
    26 //MergeSort和merge接收的都是数组的下标
    27 void MergeSort(int first, int last)
    28 {
    29     if (first == last)
    30         return;
    31     else
    32     {
    33         int mid = (first + last) / 2;
    34         MergeSort(first, mid);
    35         MergeSort(mid + 1, last);
    36         merge(first, mid, last);
    37     }
    38 }
    39 int main(void)
    40 {
    41     int last = 7;
    42     for (int i = 0; i < last + 1; i++)
    43         printf("%d  ", data[i]);
    44     printf("
    ");
    45     MergeSort(0, last);
    46     for (int i = 0; i < last + 1; i++)
    47         printf("%d  ", data[i]);
    48     return 0;
    49 }
    /* 
    输出
    ————————————————————————————————————
    8  3  2  6  7  1  5  4  
    1  2  3  4  5  6  7  8  
    ————————————————————————————————————
     */

      

       二、非递归实现(循环实现)

     1 #include <stdio.h>
     2 int data[] = {8, 3, 2, 6, 7, 1, 5, 4};
     3 int length = 8;
     4 //将两个序列合并
     5 void merge(int first1, int last1, int last2)
     6 {
     7     int *temp = new int[length]; //数组temp作为合并的辅助空间,注意这个数组和原来的数组是一样大小的,为了方便
     8     int i = first1;              //左序列第一个元素下标
     9     int j = last1 + 1;           //右序列第一个元素下标
    10     int k = first1;              //左序列第一个元素下标,用于记录合并后的初始位置(将temp复制到data上)
    11     while (i <= last1 && j <= last2)
    12     {
    13         if (data[i] <= data[j])
    14             temp[k++] = data[i++]; //升序排序,将小的放前面。如要修改,改变一下符号即可。
    15         else
    16             temp[k++] = data[j++];
    17     }
    18     while (i <= last1)         //做一些收尾工作,比如只剩下一边有几个(当然了,这几个必定是有序的了)
    19         temp[k++] = data[i++]; //注意这里的++也很有必要,因为有可能一边的序列有好几个剩下的
    20     while (j <= last2)
    21         temp[k++] = data[j++];
    22     for (i = first1; i <= last2; i++)
    23         data[i] = temp[i];
    24     delete[] temp;
    25 }
    26 //MergePass和merge接收的都是数组的下标
    27 void MergePass(int h)
    28 {
    29     int i = 0;
    30     while (i + 2 * h <= length)
    31     {
    32         merge(i, i + h - 1, i + 2 * h - 1);
    33         i = i + 2 * h;
    34     }
    35     if (i + h < length) //如果还有一块长度是h,另一块长度<h,则进行下面这种合并(主要是限制一下范围)
    36         merge(i, i + h - 1, length - 1);
    37 }
    38 int main(void)
    39 {
    40     int last = 7;
    41     for (int i = 0; i < last + 1; i++)
    42         printf("%d  ", data[i]);
    43     printf("
    ");
    44     int h = 1;
    45     while (h < length)
    46     {
    47         MergePass(h);
    48         h = 2 * h;
    49     }
    50     for (int i = 0; i < last + 1; i++)
    51         printf("%d  ", data[i]);
    52     return 0;
    53 }
    /* 
    输出
    ————————————————————————————————————
    8  3  2  6  7  1  5  4  
    1  2  3  4  5  6  7  8  
    ————————————————————————————————————
     */

    四、总结

      排序除了要了解这个大致的框架外,如果想要实现,还需要明确一下用什么来判断结束,也就是各种各样的条件

  • 相关阅读:
    [HDU 1254] 推箱子
    [POJ 1321] 棋盘问题
    Ubuntu fcitx CPU占用率很高解决方法
    超简洁git入门
    [LightOJ 1370] Bi-shoe and Phi-shoe(欧拉函数快速筛法)
    [LightOJ 1341] Aladdin and the Flying Carpet (算数基本定理(唯一分解定理))
    seekg()/seekp()与tellg()/tellp()的用法详解
    绝对路径以及相对路径中的斜杠和反斜杠
    TCP滑动窗口
    TCP的三次握手和四次挥手
  • 原文地址:https://www.cnblogs.com/coderon/p/13443776.html
Copyright © 2020-2023  润新知