zoukankan      html  css  js  c++  java
  • 归并排序

      归并排序是创建在归并操作上的一种有效的排序算法,效率为O(nlogn),1945年由冯·诺伊曼首次提出。

      归并排序的实现分为递归实现非递归(迭代)实现。递归实现的归并排序是算法设计中分治策略的典型应用,我们将一个大问题分割成小问题分别解决,然后用所有小问题的答案来解决整个大问题。非递归(迭代)实现的归并排序首先进行是两两归并,然后四四归并,然后是八八归并,一直下去直到归并了整个数组。

      归并排序算法主要依赖归并(Merge)操作。归并操作指的是将两个已经排序的序列合并成一个序列的操作,归并操作步骤如下:

    1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
    2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
    3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    4. 重复步骤3直到某一指针到达序列尾
    5. 将另一序列剩下的所有元素直接复制到合并序列尾
     //Merge sort.c
    1
    #include <stdio.h> 2 #include <limits.h> 3 4 // 分类 -------------- 内部比较排序 5 // 数据结构 ---------- 数组 6 // 最差时间复杂度 ---- O(nlogn) 7 // 最优时间复杂度 ---- O(nlogn) 8 // 平均时间复杂度 ---- O(nlogn) 9 // 所需辅助空间 ------ O(n) 10 // 稳定性 ------------ 稳定 11 12 void Merge(int A[], int left, int mid, int right)// 合并两个已排好序的数组A[left...mid]和A[mid+1...right] 13 { 14 int len = right - left + 1; 15 int temp[len]; // 辅助空间O(n) 16 int index = 0; 17 int i = left; // 前一数组的起始元素 18 int j = mid + 1; // 后一数组的起始元素 19 int k; 20 21 while (i <= mid && j <= right) 22 { 23 temp[index++] = A[i] <= A[j] ? A[i++] : A[j++]; // 带等号保证归并排序的稳定性 24 } 25 while (i <= mid) 26 { 27 temp[index++] = A[i++]; 28 } 29 while (j <= right) 30 { 31 temp[index++] = A[j++]; 32 } 33 for (k= 0; k < len; k++) 34 { 35 A[left++] = temp[k]; 36 } 37 } 38 39 void MergeSortRecursion(int A[], int left, int right) // 递归实现的归并排序(自顶向下) 40 { 41 if (left == right) // 当待排序的序列长度为1时,递归开始回溯,进行merge操作 42 return; 43 int mid = (left + right) / 2; 44 MergeSortRecursion(A, left, mid); 45 MergeSortRecursion(A, mid + 1, right); 46 Merge(A, left, mid, right); 47 } 48 49 void MergeSortIteration(int A[], int len) // 非递归(迭代)实现的归并排序(自底向上) 50 { 51 int i, left, mid, right;// 子数组索引,前一个为A[left...mid],后一个子数组为A[mid+1...right] 52 for (i = 1; i < len; i *= 2) // 子数组的大小i初始为1,每轮翻倍 53 { 54 left = 0; 55 while (left + i < len) // 后一个子数组存在(需要归并) 56 { 57 mid = left + i - 1; 58 right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够 59 Merge(A, left, mid, right); 60 left = right + 1; // 前一个子数组索引向后移动 61 } 62 } 63 } 64 65 int main() 66 { 67 int A1[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; // 从小到大归并排序 68 int A2[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; 69 int n1 = sizeof(A1) / sizeof(int); 70 int n2 = sizeof(A2) / sizeof(int); 71 int i; 72 MergeSortRecursion(A1, 0, n1 - 1); // 递归实现 73 MergeSortIteration(A2, n2); // 非递归实现 74 printf("递归实现的归并排序结果:"); 75 for (i = 0; i < n1; i++) 76 { 77 printf("%d ", A1[i]); 78 } 79 printf(" "); 80 printf("非递归实现的归并排序结果:"); 81 for (i = 0; i < n2; i++) 82 { 83 printf("%d ", A2[i]); 84 } 85 printf(" "); 86 return 0; 87 }
  • 相关阅读:
    Rmarkdown:输出html设置
    Rmarkdown:输出pdf设置
    R语言绘图:雷达图
    R语言学习笔记(十五):获取文件和目录信息
    R语言学习笔记(十四):零碎知识点(41-45)
    R语言学习笔记(十三):零碎知识点(36-40)
    JVM调优-关于jvm的一些基本概念
    Markdown常用基本语法
    redis在windows中的安装
    jvm中加载类的全过程
  • 原文地址:https://www.cnblogs.com/itsad/p/7920714.html
Copyright © 2011-2022 走看看