当前课程知识点:数据结构(上) > 第三章 列表 > (d)选择排序 > 03D-1 构思
欢迎同学们回来
与向量那一章的做法一样
列表这一章 接下来几节
也将针对列表这种结构的特点
介绍几种典型的排序算法
比如 这一节我们要介绍的就是
选择排序
这种排序算法其实并不神秘
我敢打赌 你在日常生活中
此前肯定已经甚至经常使用这种方法
举个例子
假设你有一篮子苹果 或大或小
如果你需要从小到大
把它们排成一个序列
那你会怎么做呢?
我想大家常用的一种方法
应该是这样的
首先在其中挑选出最大的
接下来 在剩下的中 挑选出最大的
也就是整个来说 次大的
再往后呢 当然是接下来的最大的
也就是整个的第三大的
不难看出 这个过程可以继续下去
直到篮子中只剩下最后那只苹果
虽然我们这里画得很夸张
但是它确实是全局最小的那个
可以看出 在这个过程中
我们所采用的策略
或者说原则非常的简单
具体来讲 就是
每一次我们只需在篮子中
找出当前最大的那只苹果
并且随即将它转移到桌子上
这个策略是如此简明
以致于我们可以反复地进行
直到最后
可见 这里每一步所做的
实质的关键动作
其实无非就是所谓的选择select
而基于这样一种选择过程
和策略的排序算法
就叫作selection sort
即便是在这门课中
我们也不是第一次接触到选择排序
我并没有骗你
回顾一下此前
我们所介绍过的bubble sort
其实它也是一个不折不扣的
selection sort
难道不是吗?
我们来看一下
在这样一个算法的过程中
我们曾经讲过
它的不变性可以表述为
整个序列总是可以
分成前后两个部分
其中后面的一个部分
是由一系列已经就位的元素组成的
它们构成了一个有序的sorted的部分
而前半部分的元素呢
数值的分布是随机的 或大或小
但是就数值而言
它们都绝对不会超过这样一条黄线
也就是说 如果从分布讲
它们都应该落在
这样一个黄色的矩形中
那这个算法我们讲过
是由一趟又一趟的扫描交换构成的
在接下来的一趟扫描交换中
最实质的故事实际上是
从当前最大的那个元素开始的
我们讲过此后的情节是确定的
也就是说 这个最大的元素
必然会和随后的邻居
以及再随后的邻居
以及再随后的邻居
不断地交换
直到它最终
被移送到
这个黄色区域的末尾
于是这个有序的S部分
就可以向左侧拓展
或者说生长一个单位
这也是我们所说的
这个算法的单调性
纵观这个过程
并且与上面的选择排序做一对比
我们会发现 二者之间惊人的相似
也就是每一次扫描交换的作用
其实实质上都等价于
找到这个最大节点
并且随即将它转移至有序
和无序子序列的分界点
从这个角度来看
起泡排序确实就是
一个不折不扣的选择排序
那反过来 既然如此
还有什么必要去专门讨论选择排序呢?
原因在于 起泡排序的效率太低
正如我们此前说过的 在最坏情况下
它需要n平方
我们注意到 这个效率
是完全可以改进的
细加观察我们可以发现
在起泡排序的过程中
所执行的计算无非两类
一类就是相邻元素的比较
另一类才是元素位置的交换
然而很遗憾
在这里将最大元素
转移至合适的位置这样一个任务
是由一系列的短距离
实际上是相邻元素之间的移动构成的
这种小步慢跑式的移动
正是低效率的来源
所以反过来
既然我们最终实际上无非
就是要将这个最大的元素
挪到最终的位置
为何不直接一次性地
来完成这项工作呢?
没错
这正是我们改进的思路
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)深度优先搜索--作业
-第六章 图--本章测验