wordpress搭建下载站点,学校网站logo怎么做,广东智慧团建系统入口,wordpress转换语言一、归并排序概述
归并排序是一种基于分治思想的经典排序算法。它的核心操作分为三个主要步骤#xff1a;分割、排序和合并。
首先是分割步骤#xff0c;将待排序的数组不断地分成更小的子数组#xff0c;直到每个子数组中只有一个元素。例如#xff0c;对于一个包含多个…一、归并排序概述
归并排序是一种基于分治思想的经典排序算法。它的核心操作分为三个主要步骤分割、排序和合并。
首先是分割步骤将待排序的数组不断地分成更小的子数组直到每个子数组中只有一个元素。例如对于一个包含多个元素的数组不断地进行对半分割直到每个子部分都只有一个元素为止。
接着是排序步骤由于单个元素的子数组本身就是有序的所以在这个阶段实际上并没有真正的排序操作。
最后是合并步骤将两个已排序的子数组合并成一个更大的有序数组。在合并过程中通过比较两个子数组的元素将较小的元素依次放入新的数组中直到两个子数组中的所有元素都被处理完毕。这个过程不断重复最终将所有的子数组合并成一个完全有序的数组。
归并排序的时间复杂度为 其中 是待排序数组的长度。这是因为每次分割操作将问题规模减半而合并操作的时间复杂度与问题规模呈线性关系。归并排序的稳定性使得它在某些特定的应用场景中具有优势特别是当需要保持相等元素的相对顺序时。总的来说归并排序以其高效和稳定的特性在计算机科学的各种领域中都有广泛的应用。
二、归并排序的核心步骤
一分割过程
递归实现分割按照深度优先方式先拆左边再拆右边设定递归终止条件。在归并排序中递归实现分割是一种常见的方法。首先找到数组的中间位置将数组分为左右两部分。然后对左右两部分分别进行递归调用继续分割直到每个子数组中只有一个元素为止。这个过程可以看作是深度优先的方式先深入到最左边的子数组进行分割然后再逐步返回并处理右边的子数组。递归的终止条件是当子数组的长度为 1 或 0 时因为单个元素的子数组本身就是有序的。
例如对于一个长度为 8 的数组首先找到中间位置分为左右两个长度为 4 的子数组。然后对这两个子数组继续进行分割直到每个子数组的长度为 1。在这个过程中递归的深度为 。
非递归实现分割借助栈机制考虑细节进行深度优先的拆分过程。非递归实现分割可以借助栈的数据结构来模拟递归的过程。首先将整个数组的范围压入栈中。然后从栈中弹出一个范围进行分割并将分割后的两个子范围压入栈中。重复这个过程直到栈为空。在这个过程中需要考虑一些细节问题比如如何确定子数组的范围、如何处理边界情况等。
例如假设我们有一个长度为 8 的数组初始时将范围 [0, 7] 压入栈中。弹出这个范围后将其分为 [0, 3] 和 [4, 7]并将这两个子范围压入栈中。接着继续弹出栈顶的范围进行分割直到每个子数组的长度为 1。
二合并过程
比较两个子数组元素较小元素放入新数组对应指针前进。在合并过程中首先比较两个已排序的子数组的首元素。将较小的元素放入一个新的数组中并将对应子数组的指针向前移动一位。然后继续比较两个子数组的下一个元素重复这个过程直到其中一个子数组的所有元素都被处理完毕。
例如假设有两个子数组 A[2, 4, 6] 和 B[1, 3, 5]。首先比较 A [0] 和 B [0]因为 12所以将 1 放入新数组中并将 B 的指针向前移动一位。接着比较 A [0] 和 B [1]因为 23所以将 2 放入新数组中并将 A 的指针向前移动一位。
处理剩余元素直接放入新数组因每一组内元素有序。当一个子数组的所有元素都被处理完毕后另一个子数组中可能还有剩余的元素。由于每个子数组本身是有序的所以可以直接将剩余的元素依次放入新数组中。
例如在上一步的例子中当比较完 A [2] 和 B [2] 后B 子数组中的元素已经全部处理完毕而 A 子数组中还有元素 4 和 6。这时可以直接将 4 和 6 依次放入新数组中。
三、归并排序的代码实现
一多种语言示例
C 语言代码实现
在 C 语言中实现归并排序通常需要以下几个关键步骤。首先是申请空间就像这样 #define N 7 void merge(int arr[], int low, int mid, int high){ int i, k; int *tmp (int *)malloc((high-low1)*sizeof(int));
接着在合并过程中比较两个子数组的元素将较小的元素放入临时数组tmp中 for(k0; left_lowleft_high right_lowright_high; k){ if(arr[left_low]arr[right_low]){ tmp[k] arr[left_low]; }else{ tmp[k] arr[right_low]; } }
最后如果一个子数组还有剩余元素直接复制到临时数组中并将临时数组的元素复制回原数组 if(left_low left_high){ for(ileft_low;ileft_high;i) tmp[k] arr[i]; } if(right_low right_high){ for(iright_low; iright_high; i) tmp[k] arr[i]; } for(i0; ihigh-low1; i) arr[lowi] tmp[i]; free(tmp); return;
C 代码实现 递归实现
C 的归并排序可以通过递归的方式实现。先找到中间位置将数组分成两部分分别进行递归排序然后再合并。 void mergeSort(int A[],int p,int r){ if(pr){ int q(pr)/2; mergeSort(A,p,q); mergeSort(A,q1,r); merge(A,p,q,r); } return; }
循环实现
也可以通过循环的方式实现归并排序。循环中每次将数组分成大小为size的子数组然后进行合并。当size大于等于数组长度时排序完成。 void mergeSortIterative(vectorint arr) { int n arr.size(); for (int size 1; size n; size * 2) { for (int left 0; left n - size; left 2 * size) { int mid left size - 1; int right min(left 2 * size - 1, n - 1); merge(arr, left, mid, right); } } }
这种方式展示了一些精妙的代码优化成果通过循环逐步合并子数组减少了递归带来的开销。
Java 代码实现 手写归并排序
在 Java 中手写归并排序需要明确功能、寻找递推关系、确定终止条件。首先确定分界点将待排序数组分成左右两部分然后递归处理左右数组部分。最后将排序好的左右两部分数组合并成新数组并确保合并后的数组依然有序。 public static int[] temp; public static void merge_sort(int[] q, int l, int r) { if (l r) { return; } int mid (l r) / 2; merge_sort(q, l, mid); merge_sort(q, mid 1, r); int k 0, i l, j mid 1; temp new int[r - l 1]; while (i mid j r) { if (q[i] q[j]) { temp[k] q[i]; } else { temp[k] q[j]; } } while (i mid) { temp[k] q[i]; } while (j r) { temp[k] q[j]; } for (i l, j 0; i r; i, j) { q[i] temp[j]; } }
分析性能
归并排序在 Java 中的时间复杂度为 其中 是待排序数组的长度。空间复杂度为 因为需要一个临时数组来存储排序过程中的数据。归并排序是稳定的排序算法这意味着相等元素的相对顺序在排序后不会改变。
Python 代码实现 多路归并排序
在 Python 中可以实现多路归并排序。多路归并排序通常借助优先队列或自己实现小顶堆来处理大规模数据集。首先将每个数据块分别排序然后将这些有序的数据块进行多路归并。 def merge(lst1, lst2): lst3 [] i1, i2 0, 0 n1, n2 len(lst1), len(lst2) while i1 n1 and i2 n2: if lst1[i1] lst2[i2]: lst3.append(lst1[i1]) i1 i1 1 else: lst3.append(lst2[i2]) i2 i2 1 if i1 n1: for i in lst2[i2:]: lst3.append(i) else: for i in lst1[i1:]: lst3.append(i) return lst3 def mergeSort(nums): n len(nums) if n 1: return nums m n // 2 left mergeSort(nums[:m]) right mergeSort(nums[m:]) return merge(left, right)
处理大规模数据集
对于大规模数据集多路归并排序可以有效地利用内存和处理器资源提高排序效率。通过将数据集分成多个较小的数据块分别进行排序然后再进行合并可以减少内存占用和排序时间。
PHP 代码实现 展示合并和拆分过程的具体代码
在 PHP 中归并排序可以通过递归和非递归两种方式实现。以下是递归方式的实现代码 function mergeSort($arr, $left, $right) { if ($left $right) { $mid floor(($left $right) / 2); mergeSort($arr, $left, $mid); mergeSort($arr, $mid 1, $right); merge($arr, $left, $mid, $right); } } function merge($arr, $left, $mid, $right) { $i $left; $j $mid 1; $temp array(); while ($i $mid $j $right) { if ($arr[$i] $arr[$j]) { $temp[] $arr[$i]; $i; } else { $temp[] $arr[$j]; $j; } } while ($i $mid) { $temp[] $arr[$i]; $i; } while ($j $right) { $temp[] $arr[$j]; $j; } for($k 0; $k count($temp); $k) { $arr[$left $k] $temp[$k]; } }
非递归方式的实现代码如下 function mSort($arr) { $len count($arr); $size 1; while ($size $len - 1) { $left 0; while ($left $size $len - 1) { $mid $left $size - 1; $right $mid $size; if ($right $len - 1) { $right $len - 1; } merge($arr, $left, $mid, $right); $left $right 1; } $size * 2; } } function merge($arr, $left, $mid, $right) { $i $left; $j $mid 1; $temp array(); while ($i $mid $j $right) { if ($arr[$i] $arr[$j]) { $temp[] $arr[$i]; $i; } else { $temp[] $arr[$j]; $j; } } while ($i $mid) { $temp[] $arr[$i]; $i; } while ($j $right) { $temp[] $arr[$j]; $j; } for ($i $left, $k 0; $i $right; $i, $k) { $arr[$i] $temp[$k]; } }
这些代码展示了归并排序在 PHP 中的具体实现帮助理解归并排序的整体流程。
二代码性能分析
时间复杂度 无论在最坏、最佳还是平均情况下归并排序的时间复杂度均为 。这是因为每次分割操作将问题规模减半而合并操作的时间复杂度与问题规模呈线性关系。例如对于一个长度为 的数组分割操作需要进行 次每次分割后的合并操作需要 的时间复杂度所以总的时间复杂度为 。空间复杂度 归并排序在排序过程中需要使用辅助数组空间复杂度为 。这是因为在合并过程中需要一个临时数组来存储合并后的结果。例如对于一个长度为 的数组在合并过程中需要一个长度为 的临时数组来存储合并后的结果。稳定性 归并排序是一种稳定排序。这意味着在排序过程中相等元素的相对顺序不会改变。例如对于一个包含多个相等元素的数组归并排序会保持这些相等元素的相对顺序不变。是否原地排序 归并排序不是原地排序因为它需要使用辅助数组来存储合并后的结果。原地排序是指在排序过程中不需要额外的存储空间只需要在原数组上进行操作。例如冒泡排序、插入排序和选择排序都是原地排序算法。
四、归并排序的应用场景
归并排序在处理大规模数据集方面具有显著优势尤其适用于小内存排序大文件等情况。
例如在面对外存中有 100G 的字符串文件而只有 1G 内存的情况下归并排序可以发挥重要作用。首先将 100G 的内容分成若干个小部分每个部分不超过 500MB。分别读取这些小部分进行排序然后写入到外存中这样就得到了若干个已经排好序的小部分。接着进行多路归并排序对于多个已经排好序的小部分每次取出它们各自的最小值找到最小值中的最小值写入到外存同时将最小值所在外存区域指针向右移动。每次比较最小值需要比较 k-1 次总共有 n-1 轮所以时间复杂度为 O ((n-1)*(k-1))。这里还可以使用胜者树完全二叉树优化找最小值的过程对第一次的查找建立一颗胜者树找到最小值后读取最小值所在外存区域的新值然后修改胜者树对应节点的值沿着从该结点到根结点的路径修改这棵二叉树最多操作 log (k) 次。这样总体排序的时间复杂度就可以降为 O (nlogk)。
此外使用 Python 实现多 (K) 路归并外部排序可以解决小内存排序大文件问题。绕不开归并核心思想分治先拆成小文件再排序最后合并所有碎片文件成一个大文件。首先大文件拆分成多个 block_size 大的小文件每个小文件排好序。然后将拆分成的小文件合并起来然后将归并的东西写到大文件里面去这里用到的是多路归并的方法。
在实际工作中多个有序数列合并成一个大文件或多个大文件合并成一个并排序的需求常见并不少见。比如现在有四路数据a0:[1, 3, 6, 7]a1: []a2: [3, 5, 7, 19]a3: [9, 12, 87, 98]。可以使用多路归并排序的方法先保存每路最小值用 min_map 保存每一路的当前最小值然后获取最小值中的最小值将其取出并检查被取出值的那一路是否还剩下其他元素如果存在则修改 min_map 里面对应的值如果不存在则删除掉 min_map 里面对应的记录以表示该路已经没有元素需要遍历了。最终将多个有序数组合并起来。
总的来说归并排序以其高效的处理大规模数据集的能力在实际应用中具有广泛的应用场景。 文章转载自: http://www.morning.mfnsn.cn.gov.cn.mfnsn.cn http://www.morning.eshixi.com.gov.cn.eshixi.com http://www.morning.rdmn.cn.gov.cn.rdmn.cn http://www.morning.gnghp.cn.gov.cn.gnghp.cn http://www.morning.jwsrp.cn.gov.cn.jwsrp.cn http://www.morning.wtyqs.cn.gov.cn.wtyqs.cn http://www.morning.tgwfn.cn.gov.cn.tgwfn.cn http://www.morning.kfstq.cn.gov.cn.kfstq.cn http://www.morning.npmcf.cn.gov.cn.npmcf.cn http://www.morning.rzsxb.cn.gov.cn.rzsxb.cn http://www.morning.qcymf.cn.gov.cn.qcymf.cn http://www.morning.nzmhk.cn.gov.cn.nzmhk.cn http://www.morning.ylrxd.cn.gov.cn.ylrxd.cn http://www.morning.lnmby.cn.gov.cn.lnmby.cn http://www.morning.prmbn.cn.gov.cn.prmbn.cn http://www.morning.dnvhfh.cn.gov.cn.dnvhfh.cn http://www.morning.dbddm.cn.gov.cn.dbddm.cn http://www.morning.wchcx.cn.gov.cn.wchcx.cn http://www.morning.rftk.cn.gov.cn.rftk.cn http://www.morning.mxdiy.com.gov.cn.mxdiy.com http://www.morning.smry.cn.gov.cn.smry.cn http://www.morning.tqgmd.cn.gov.cn.tqgmd.cn http://www.morning.cylbs.cn.gov.cn.cylbs.cn http://www.morning.llqky.cn.gov.cn.llqky.cn http://www.morning.bgbnc.cn.gov.cn.bgbnc.cn http://www.morning.lmpfk.cn.gov.cn.lmpfk.cn http://www.morning.lsqmb.cn.gov.cn.lsqmb.cn http://www.morning.yntsr.cn.gov.cn.yntsr.cn http://www.morning.ckcjq.cn.gov.cn.ckcjq.cn http://www.morning.klrpm.cn.gov.cn.klrpm.cn http://www.morning.wnhgb.cn.gov.cn.wnhgb.cn http://www.morning.ykmtz.cn.gov.cn.ykmtz.cn http://www.morning.fkgqn.cn.gov.cn.fkgqn.cn http://www.morning.qxjck.cn.gov.cn.qxjck.cn http://www.morning.ntzbr.cn.gov.cn.ntzbr.cn http://www.morning.easiuse.com.gov.cn.easiuse.com http://www.morning.jwlmm.cn.gov.cn.jwlmm.cn http://www.morning.kqnwy.cn.gov.cn.kqnwy.cn http://www.morning.dysgr.cn.gov.cn.dysgr.cn http://www.morning.dmcxh.cn.gov.cn.dmcxh.cn http://www.morning.jpkhn.cn.gov.cn.jpkhn.cn http://www.morning.kmbgl.cn.gov.cn.kmbgl.cn http://www.morning.yhplt.cn.gov.cn.yhplt.cn http://www.morning.hxfrd.cn.gov.cn.hxfrd.cn http://www.morning.dfndz.cn.gov.cn.dfndz.cn http://www.morning.mcjxq.cn.gov.cn.mcjxq.cn http://www.morning.qfgwx.cn.gov.cn.qfgwx.cn http://www.morning.c7512.cn.gov.cn.c7512.cn http://www.morning.hjjfp.cn.gov.cn.hjjfp.cn http://www.morning.xhxsr.cn.gov.cn.xhxsr.cn http://www.morning.gfmpk.cn.gov.cn.gfmpk.cn http://www.morning.kgnrh.cn.gov.cn.kgnrh.cn http://www.morning.ndmbz.cn.gov.cn.ndmbz.cn http://www.morning.brzlp.cn.gov.cn.brzlp.cn http://www.morning.lgrkr.cn.gov.cn.lgrkr.cn http://www.morning.mtktn.cn.gov.cn.mtktn.cn http://www.morning.rnsjp.cn.gov.cn.rnsjp.cn http://www.morning.tpps.cn.gov.cn.tpps.cn http://www.morning.gnghp.cn.gov.cn.gnghp.cn http://www.morning.sjqml.cn.gov.cn.sjqml.cn http://www.morning.jbfzx.cn.gov.cn.jbfzx.cn http://www.morning.pfnwt.cn.gov.cn.pfnwt.cn http://www.morning.sgmis.com.gov.cn.sgmis.com http://www.morning.zxxys.cn.gov.cn.zxxys.cn http://www.morning.qphgp.cn.gov.cn.qphgp.cn http://www.morning.yhpl.cn.gov.cn.yhpl.cn http://www.morning.stbfy.cn.gov.cn.stbfy.cn http://www.morning.ylph.cn.gov.cn.ylph.cn http://www.morning.xjmyq.com.gov.cn.xjmyq.com http://www.morning.wjlrw.cn.gov.cn.wjlrw.cn http://www.morning.ndlww.cn.gov.cn.ndlww.cn http://www.morning.xcxj.cn.gov.cn.xcxj.cn http://www.morning.ghjln.cn.gov.cn.ghjln.cn http://www.morning.dgxrz.cn.gov.cn.dgxrz.cn http://www.morning.trtdg.cn.gov.cn.trtdg.cn http://www.morning.lmhh.cn.gov.cn.lmhh.cn http://www.morning.sqfrg.cn.gov.cn.sqfrg.cn http://www.morning.lsnnq.cn.gov.cn.lsnnq.cn http://www.morning.ctqlq.cn.gov.cn.ctqlq.cn http://www.morning.mstrb.cn.gov.cn.mstrb.cn