当前课程知识点:数据结构(上) > 第一章 绪论(下) > (d)算法分析 > 01d-4: 实例:非极端元素+起泡排序
上述这些方法 也可以推广至一般性的办法
来看一个简单的实例
对于任何整数子集S
当然 作为集合 其中的元素肯定是互异的
如果其中的元素的个数至少有三个
那么 我们需要找出
其中的某一个所谓的非极端的元素
这个元素在其中既不是最大的也不是最小的
方法呢 如下
从S中 只要任意取出三个元素就够了
我们刚才说了 这是个集合 其中元素是互异的
所以这样任意取出三个元素X Y Z
肯定也是互异的
剩下的两步 实际上就是在其中
找到这三者中间的一个非极端元素
排除掉其中的最小的和最大的
剩下来的那个居中的元素
就是这三个元素中的非极端元素
而且这个元素 不管是X、Y或者Z
同时也必然是原来整个子集的非极端元素
这个算法 本身没有什么太多的意味
但是 它告诉我们
确实在某些情况下
无论你这个问题的规模N有多大
某些算法可能所需要的时间
都是一个固定不变的常数
再来看一个更一般的例子
也就是 我们希望针对所谓的排序问题
给出第一个算法:起泡排序
所谓的排序的任务就是将N个对象
在这里 不妨简化作整数
按顺序的排列 比如说
一般都是按所谓的非降次序
所谓的起泡算法 只是其中的
一个最基本的方法
它的思路 是基于这样一个观察事实
在一个已经排序
称作有序的序列中
任何一对相邻的元素
无论是它们 还是它们
抑或是它们
都必然是顺序的
反之 如果有一个序列不是有序的
我们称之为无序的
其中必然能找到这样一对 也是紧邻的
但是大小次序 正好是颠倒的元素
这种元素可能不是很多
但是在无序序列中
像这个例子指示的那样
至少会包含一对
所以 这个算法的思路就是
逐步的去消除这种
相互紧邻的逆序的元素
方法是通过所谓的扫描交换
也就是说 反复地去扫描这个序列
每一次扫描 我们称作一趟
在每一趟这样的扫描过程中
确实发现了有这样的
逆序的紧邻元素
就将二者位置交换
如果在某一趟的过程中
发现没有这种元素 就可以终止
否则的话 这种扫描将持续的
一趟一趟的执行下去
整个起泡排序的计算过程
可以精确地描述为这样一段代码
这是典型的二重循环的模式
外循环对应的就是
一趟一趟的扫描交换
而内循环执行扫描交换
在每一次内循环中
它确实会去逐一地检查
每一对相邻的元素
如果它们确实是逆序的
就会令二者交换位置
同时 大家注意到
这里有一个标志sorted
从语意上讲 它表示的是
整个这个序列是否已经有序
在当前的这一趟扫描过程中
如果我们确实已经发现了有一对逆序对
那我们就不能保证整体是有序的
所以必须把它清除
而这个清除以后的标志
在下一趟扫描的起始之前
会经过翻转
并且初始化为一个true
如果是这样的话
所以使得这个扫描可以
一趟一趟地执行下去
当然我们也可以反过来看
什么时候会退出呢
既然你要赋值以后 等于false
在翻转之前 这个sorted就应该是true
应该是上一趟的初始值
那么 它就必然不会执行这一句
换而言之 就必然不会存在逆序对
正如我们刚才所说的
整体这个序列 已经有序了
下面通过这个例子介绍
典型的一些方法 来证明一个算法
为什么是正确的 必然是终止的
以及 具体它的复杂度又该如何度量
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)深度优先搜索--作业
-第六章 图--本章测验