从之前的学习可以看到,对大型vectory要求的排序,选择排序算法显然不符合要求,因为运行时间与输入问题规模大小的平方成比例增加,对于以线性顺序处理向量的元素的大多数排序算法也是如此。 所以要采用不同的方法来开发更好的排序算法。我们可以试着反过来思考。

强大的分治法(divide-and-conquer)

分治法的具体详见 C++抽象编程——递归简介(1)——递归范式 我们先来看看排序算法的性能为什么在问题规模增大后变得如此糟糕?我们之前分析过二次复杂度(即O(N^2)类)的基本特征是,随着问题的大小增加,运行时间增加了问题规模的两倍(比如问题规模增加2倍,那么运行时间要增加4倍)然而,反过来我们可以这样想。 如果将二次问题的大小除以2,则可以将运行时间减少相同的四倍。 也就是说我们可以将vector除以一半,然后应用递归的方法继续将问题的规模拆分,就可以成倍的减少所需的排序时间。

举个例子,假设你有一个很大的vector需要排序。如果将vector分成两半,然后使用选择排序算法对这些片段进行排序,会发生什么? 因为选择排序是的复杂度是二次的,每个较小的vector需要原始时间的四分之一(问题规模减少了2倍,时间就提高4倍)。 当然,你需要对这两半分别进行排序,但是排序两个较小vector所需的总时间仍然是排序原始vector所需的时间的一半。如果分开一个vector的两半可以简化整个vector排序的问题,我们将能够大大减少排序需要的总时间。更重要的是,一旦发现如何在一个地方提高性能,就可以使用相同的算法递归地对每一个进行排序。 为了确定分治法是否适用于这个排序问题,我们需要确定一个问题,即将vector分为两个较小的vector,然后对每个vector进行排序是否有助于解决一般问题(也就是拿一个实例来分析一下)。假设你从一个包含以下八个元素的vector开始排序:

如果将8个元素的vector划分为长度为4的两个vector,然后对每个较小的vector进行排序,就会得到下图:

现在我们需要从这些较小的vector中取出值,并将它们以正确的顺序放回到原始vector中。

合并两个vector

从较小的排序vector重组成完整的vector比排序本身要简单得多。这个过程我们称为合并(merging)即完整排序中的第一个元素必须是v1中的第一个元素或v2中的第一个元素,以较小者为准。回到这个例子当中, 1. 我们新组成的的vector中的第一个元素是第二个vector(v2)中的第一个元素。然后将该元素添加到空的向量vec,此时我们把v2的19叉掉,表示已经取出,我们下图的结果

2. 再来一次,下一个元素只能是两个较小向量之一中的第一个未取出的元素。比较v1中的25与v2中的30,并选择前者:

3. 重复此过程,从v1或v2中选择较小的值,直到重构整个vector

合并排序算法

合并操作与递归分解相结合,产生了一种称为合并排序的新的排序算法,可以直接实现。 算法的基本思想可以概括如下:

1. 检查vector是否为空或只有一个元素。如果是这样,它肯定已经被排序。此条件用于定义递归的simple case。

2. 将vector分成两个较小的vector,每个vector的大小是前者的一半(意味着,不是值分成两个vector,而是每个分开的vector还可以继续分,重复这个过程)

3. 递归地对每个较小的vector进行排序。

4. 清除原始的vector,使其再次为空。(用来储存新的排序好的数字)

5. 将两个排序好的vector合并回原来的vector。

合并排序的C++代码

合并排序思路简单,但是实现起来并不那么容易,下面是本人写的C++代码,在VS2015中编译通过:

/*

运行效果如图:

合并排序算法的代码可以整齐地分为两个函数:排序和合并。 排序代码直接来自算法的步骤。在检查特殊情况后,算法将原始vector分为两个较小的v1和v2。一旦sort代码将所有元素复制到v1或v2中,v1,V2就已经被创建,其余的函数会递归地排序这些vector,最后清除原始vector,然后调用merge来重新组合vector,从而实现合并排序。 实际上大部分的工作是通过合并函数完成的,该函数采用目标vec,以及较小的向量v1和v2。指标p1和p2标记跟踪每一个vector的下标。 在循环的每个循环中,该函数从v1或v2选择一个元素取较小者,并将该值添加到vec的末尾。一旦两个较小的vector中的任何一个的元素被取尽,该函数可以简单地从另一个vector中直接复制元素而再比较它们。实际上,因为这些向vector中的其中一个已经在第一个while循环退出时已经耗尽,所以该函数可以将vector的其余部分复制到vec。 其中一个vector为空,相应的while循环将完全不执行。

这里说一下,v1[p1++],其实我们都知道 i++返回的 i的值是自增1的。但是这个运算符返回的是自增前的值。也就是说比如 i = 2,执行

i++;

之后,就是 i = 3,但是 (i++)这个整体的值就还是 2(可以写个程序试试)。 所以说

v1[p1++]

这句代码等价于:

 v1[p1]; p1 ++;

下一篇的文章我们就去分析一下这个算法的复杂度

c++两个vector合并_数据结构——算法初步(4)——合并排序算法相关推荐

  1. 排序算法java 简书_史上最全经典排序算法总结(Java实现)

    查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中.因为其实现代码较短,应用较常见.所以在面试中经常会问到排序算法及其相关的问题.但万变不离其宗,只要熟悉了思想,灵活运用也不是难事.一般在 ...

  2. 数据结构与算法:十大排序算法之归并排序

    数据结构与算法:十大排序算法之归并排序 package TopTenSortingAlgorithms;/*** 归并排序:Java** @author skywang* @date 2014/03/ ...

  3. 南京邮电大学数据结构实验四(各种排序算法)

    南邮数据结构实验报告四----各种排序算法 一.各类算法 (一)简单选择排序 (二)直接插入排序 (三)冒泡排序 (四)快速排序 (五)两路合并排序 (六)堆排序 二.全部排序整合+时间测试 三.算法 ...

  4. 数据结构与算法(五)排序算法篇

    排序算法篇 恭喜各位小伙伴来到最后一部分:排序算法篇,数据结构与算法的学习也接近尾声了,坚持就是胜利啊! 一个数组中的数据原本是凌乱的,但是由于需要,我们需要使其有序排列,要实现对数组进行排序我们之前 ...

  5. 堆排序稳定性举例_最常用的 8 个排序算法:从原理到改进,再到代码兑现透彻解析...

    1. 关于排序 很高兴与大家一起探讨计算机科学中的基础算法之排序算法.排序算法是非常基础同时又应用非常广泛的算法,无论在工作还是在生活中,比如: 数据库脚本,如MSSql, MySql, NoSql ...

  6. 数据结构与算法:十大排序算法之堆排序

    数据结构与算法:十大排序算法之堆排序 堆排序可以说是选择排序的优化 package TopTenSortingAlgorithms;import java.util.Arrays; import ja ...

  7. 数据结构与算法:十大排序算法之冒泡排序

    数据结构与算法:十大排序算法之冒泡排序 package array;import java.util.Arrays;//冒泡排序 //1.比较数组中两个相邻的元素,如果第一个数比第二个数大,我们就交换 ...

  8. 数据结构(七)高级排序算法——归并、快速排序

    一.归并排序 1.排序原理 归并排序算法是一种利用了分治算法思想实现的排序算法,这种排序算法是基于有序数组合并的归并排序算法的基本思想就是:判断一个待排序序列的长度,只要这个待排序序列的长度是超过1的 ...

  9. 《数据结构与算法》实验:排序算法实验比较——选择排序 堆排序

    <数据结构与算法>实验和课程Github资源 <数据结构与算法>实验:线性结构及其应用--算术表达式求值 <数据结构与算法>实验:树型结构的建立与遍历 <数据 ...

  10. 数据结构几种常见的排序算法

    学习过经典的冒泡排序算法后,我们将继续深入学习,了解更多算法排序 插入排序 直接插入排序 直接插入排序其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,指导所有记录插 ...

最新文章

  1. NoSql中的B-tree、B+tree和LSM-tree
  2. SwiftUI3.0用户登录输入非空校验经典案例
  3. C++ 学习之旅(14)——构造函数constructors和析构函数destructors
  4. CodeBlocks问题解决
  5. python算法应用(二)——一些使用技巧
  6. 鼠标放到图片上替换图片,改变样式。
  7. js 操作java对象_[Java教程]js 对象操作 对象原型操作 把一个对象A赋值给另一个对象B 并且对象B 修改 不会影响 A对象...
  8. 七牛云主机全线升级,「两大资源池」实现多云容灾
  9. BT种子文件 bencoding编码详细解析
  10. c语言 鼠标宏,鼠标宏设置软件下载 Mini Mouse Macro(鼠标宏设置工具) v7.2.0.0 免费安装版 下载-脚本之家...
  11. Ribbon界面开发(C++)
  12. Ray Dalio:经济机器是怎样运行的 (时长30分钟) 薛兆丰经济学讲义
  13. python计算正数,负数和复数的平方根
  14. 关于计算机团队名字大全集,好听的团队名字大全
  15. 每当这些游戏发售,各国旅游部门就笑得合不拢嘴了
  16. 如何确保网站的安全性
  17. 微信如何屏蔽别人发来的消息,如何屏蔽微信消息
  18. 计算机发展前景思维导图,计算机绘制思维导图有什么优势
  19. 午芯高科WXP380气压传感器
  20. 可视化文本处理模板代码

热门文章

  1. kafka内存不断增加_分布式发布订阅消息系统Kafka 为什么快
  2. 我的世界服务器显示不出地图,为什么我的世界服务器地图加载不了
  3. (JAVA)IO流之读写单个字节和复制文本文件
  4. 【名额有限】云开发AI拓展能力等你来体验!
  5. B-JUI文档、下载
  6. 重写、重构、重载区别
  7. 5233杨光--Linux第一次实验
  8. GridView应用整理
  9. 几个实用的Servlet应用例子-入门、cookie、session及上传文件
  10. [Kali][VMware][2020][窗口大小][分辨率]高分辨率自适应