当前课程知识点:数据结构(上) > 第二章 向量(下) > (f)归并排序 > 02F-1 归并排序:构思
同学们好
在这一节我们继续介绍向量的排序算法
在上一节
我们介绍过起泡排序
也就是Bubble Sort
我们看到 尽管它可以从很多侧面进行优化
但是从最坏的情况 这个角度而言
至少都需要n平方的时间
在课后 如果同学们已经学习过
我们所推荐的一些内容的话
大家会记得
如果采用包括Bubble sort在内的
我们常规的那些所谓基于比较式的算法
也就是comparison based algorithm
那么求解排序问题都存在一个下界
n*logn
我们的问题从此展开
也就是说
在这样一个n平方的上界
到n*logn的下界之间
是否存在一些其它的
相对于n平方而言 更好的算法
甚至于我们能不能指望
有一个算法 即使在最坏的情况下
也只需要n*logn的时间
就能完成排序呢?
答案就蕴含在这一节的主题里
也就是归并排序Merge Sort
归并排序算法是
分治策略在算法设计中应用的又一个典型
这个算法最初是由冯·诺依曼编码实现的
尽管算法的思想出现地要更早一些
我们说 所谓的分治策略 在这里就是说
将待排序的那个序列
无论是本章所介绍的向量
还是下一章所介绍的列表
一分为二
我们可以看到这种分法很快捷
只需要O(1)的时间
其实就是分为左右两部分
如果把它水平地画出来的话
接下来 对于划分出的两个子序列
分别去做递归地求解
也就是递归地排序
而当两个子序列已经分别有序之后
我们接下来要解决的一个问题
就是将它们合并
准确地讲 是归并merge
从而构成一个完整的有序序列
我们来看右侧这个例子
这是由八个元素组成的一个向量
按照刚才所说的思路
面对这样一个相对还比较大的向量
我们能够做的事情 首先是分
沿左右 划分为左和右两个子序列
这两个子序列递归地求解的过程中
依然发现还是相对比较大
所以它们会继续递归地、各自地进行划分
继续分为左左、左右
以及右左和右右四个子序列
同样 它们还是不够平凡
所以我们最后还要对这四个子序列
继续地一分为二
最终八个元素各自成为一个独立的序列
这个时候从递归地角度讲
就抵达了递归基
所有这些元素都已经不需要
再继续划分下去了
因为它们各自有序了
所以如果说前面半层
是做无序向量的递归分解
接下来 就要通过逐层的合并
使之逐渐地变成一个大一点的
更大一点的 直到最后那个有序的序列
我们可以看到
每一次都是将两个
已经是有序的子序列
合并为一个有序的子序列
包括这个、这个、这个
好 然后再继续
相邻的子序列逐对地合并
构成再更大的序列
以及再来一个
好
最后这两个各自有序的子序列
再逐对地合并
最终得到整体的序列
那么我们要说的是
如果果真能像这里所说的那样
我们就应该能够得到一个
总体是n*logn的算法
因为从递推的角度来看
整体的排序 如果需要是T(n)的时间
那么它所要做的事情
就是递归地去求解2个
各自规模为原先一半的问题
然后最重要的是要加上一个
分以及和累计的时间
也就是O(n)
这样一个典型的递推式
我们应该已经非常熟悉了
它得到的解就是n*logn
那么现在接下来的技术细节就是
如何来兑现这一点呢?
我们可以看到 从这里的分来讲
是非常简单的
不用多解释
递归 我们也可以交给递归的机制去做
所以这里核心的任务是在怎么进行合并
或者准确地讲
是怎么将两个已经有序的序列
归并成一个更大的序列
这也是这个算法最关键的细节和技巧
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)计算
--演示
--(a)计算--作业
-(b)计算模型
-(b)计算模型--作业
-(c)大O记号
-(c)大O记号--作业
-(d)算法分析
-(d)算法分析--作业
-(e)迭代与递归
-(e)迭代与递归--作业
-(xc)动态规划
-- 演示
-(xc)动态规划--作业
-本章测验--作业
-(a)接口与实现
--02A-5 复制
-(a)接口与实现--作业
-(b)可扩充向量
-(b)可扩充向量--作业
-(c)无序向量
--02C-1 概述
--02C-3 插入
--02C-6 查找
--02C-8 遍历
-(c)无序向量--作业
-(d1)有序向量:唯一化
-(d1)有序向量:唯一化--作业
-(d2)有序向量:二分查找
-(d2)有序向量:二分查找--作业
-(d3)有序向量:Fibonacci查找
-(d3)有序向量:Fibonacci查找--作业
-(d4)有序向量:二分查找(改进)
-(d4)有序向量:二分查找(改进)--作业
-(d5)有序向量:插值查找
-第二章 向量(下)--(d5)有序向量:插值查找
-(e)起泡排序
--02E-2 改进
--02E-3 反例
-(e)起泡排序--作业
-(f)归并排序
-(f)归并排序--作业
-本章测验--作业
-(a)接口与实现
--03A-4 实现
-(a)接口与实现--作业
-(b)无序列表
--03B-2 查找
-(b)无序列表--作业
-(c)有序列表
--03C-3 查找
-(c)有序列表--作业
-(d)选择排序
--03D-1 构思
--03D-2 实例
--03D-3 实现
--03D-4 推敲
--03D-6 性能
-(d)选择排序--作业
-(e)插入排序
--03E-1 经验
--03E-2 构思
--03E-3 对比
--03E-4 实例
--03E-5 实现
-(e)插入排序--作业
-(xd)习题辅导:LightHouse
-本章测验--作业
- (a)栈接口与实现
--04A-1 栈
--04A-2 实例
--04A-3 实现
- (a)栈接口与实现--作业
-(c1)栈应用:进制转换
-第四章 栈与队列--(c1)栈应用:进制转换
-(c2)栈应用:括号匹配
-(c2)栈应用:括号匹配--作业
-(c3)栈应用:栈混洗
-第四章 栈与队列--(c3)栈应用:栈混洗
-(c4)栈应用:中缀表达式求值
-(c4)栈应用:中缀表达式求值--作业
-(c5)栈应用:逆波兰表达式
-第四章 栈与队列--(c5)栈应用:逆波兰表达式
-(d)队列接口与实现
--04D-1 接口
--04D-2 实例
--04D-3 实现
-第四章 栈与队列--本章测验
-(a)树
--05A-1 动机
--05A-2 应用
-(a)树--作业
-(b)树的表示
--05B-2 父亲
--05B-3 孩子
-第五章 二叉树--(b)树的表示
-(c)二叉树
-(c)二叉树--作业
-(d)二叉树实现
-(d)二叉树实现--作业
-(e1)先序遍历
-(e1)先序遍历--作业
-(e2)中序遍历
-第五章 二叉树--(e2)中序遍历
-(e4)层次遍历
-第五章 二叉树--(e4)层次遍历
-(e5)重构
-(e5)重构--作业
-本章测验--作业
-(a)概述
-(a)概述--作业
-(b1)邻接矩阵
-(b1)邻接矩阵--作业
-(c)广度优先搜索
--06C-2 策略
--06C-3 实现
--06C-5 实例
-(c)广度优先搜索--作业
-(d)深度优先搜索
--06D-1 算法
--06D-2 框架
--06D-3 细节
-(d)深度优先搜索--作业
-第六章 图--本章测验