当前课程知识点:数据结构(上) > 第一章 绪论(上) > (b)计算模型 > 01b-8: RAM实例
我们来看基于RAM模型
实现的一个具体算法实例
这个算法的功能是
在向下取整的意义上的除法
具体来说 对于任何一个非负整数c
和正整数d 我们都需要在做完除法之后
再实施向下取整 得到一个整数
那么这个输出
实际上也就是不超过c/d的那个最大整数
我们可以将它表述为
在所有那些与d相乘以后
不大于c的整数x中的最大值
也可以等效的表述为
在所有乘以d以后严格的小于c+1的
那些整数x中的最大值
这样一种重新的表述
其实不光是文字上的一个转换
更重要的是
它为我们提供了一个对应的算法思路
我们可以将它表述并且实现如下
具体来讲 我们需要保留c+1
并且以它为基础 反复的从中去减除d
因为RAM模型只支持加或者减运算
不断的减除
直到对应的那个寄存器R[0]发生下溢
也就是说 它不再是一个正数
这个时候 我们统计下
在此之前所做过减法运算次数
那么它就是我们所要得到的输出
我们可以将整个这个思路兑现如下
因为这里所有的加法运算和减法运算
都不允许直接对常数进行
而我们一上来就需要做个预处理
对c+1 所有需要利用常数赋值语句
将这个增量1预先的存到一个寄存器
比如R[3]中去
所有接下来我们对R[0]
也就是最初输入的c
加R[3]之后 实际上效果就是c自增
所以在经过这样的预处理之后
c+1确实被存放到R[0]中去了
那么接下来 从第二句开始
如果注意到这里有个goto第2个语句的话
我们就知道这实际上是构成了一个循环
那么这个循环是做什么事呢
正如我们前面所说的那样
它是不断的需要从刚才那个量里头去
刨除掉d
d本身也是作为输入的一部分
已经事先存放在1号寄存器中了
所以每次做的事情
就是从刚才经过预处理以后
存放的实际上是c+1的
那个寄存器R[0]中减除掉d
不断的减除 每减除一次
我们刚才说过
要相应的把计数器累计
这个计数器在哪呢
在我们这里取做的就是R[2]
第2个寄存器 它的初值是0
所以每一次它都要自加
加一个1 而加的这个1
依然是通过我们预先赋值
那个常数存到R[3]中去来实现
经过了这样一次自减
经过了一次计数器的累加之后
我们这个时候就要判断 R[0]
也就是c+1初始的那个数
是否已经不再是一个正数了
如果它还是正数
那就说明还没有减除完
这个时候我们可以通过goto语句
像刚才所说的继续执行这一步
所以反过来说
如果我们有朝一日执行到了第5条语句
那就说明R[0]经过若干次减除以后
已经不再是一个正数
而这个时候呢
我们大致就可以返回这个x
当然 通过精细的分析我们会发现
实际上这个数值是差一的
所以这里头我们还要将R[3]
也就是原来存放的这个常数1
再减一次
经过了这样一次减法以后
再把这个数值返回回去
才会得到真正准确的
我们所需要的那个向下取整的除法值
那么我们把这样的一个
具体实例也罗列出来了
具体来说就是
对于c=12以及d=5来做的一个除法
不难发现 如果不取整的话是2.4
所以向下取整的话 应该得到的是2
不出意外 在我们对照代码
逐行逐条的将整个寄存器序列的内容
作一罗列之后
我们会发现 最终在R[0]这个位置上
会得到并且返回我们
所需要的那个值 也就是2
那么这个算法的正确性
以及更多的例子的给出
留给同学们在课后完成
而我们这里需要向大家
传达的一个重要的概念
是这张表所暗示的
也就是说 我们不光可以把整个计算过程
逐次罗列出来
更重要的是 正像刚才所说的那样
我们将整个计算过程所需要的计算成本
转化为了这个表的规模 或者说它的高度
具体来说就是它的行数
其实就是执行的基本操作的次数
按照我们刚才的推断
实际上就是我们这个算法
所需时间的一个最客观的度量
而这个度量是清晰的 明确的
可比较的 而且没有歧义的
概括一下
我们通过图灵机模型和RAM模型
给大家一个清晰的尺度
这个尺度确实可以用来对算法进行度量
我们可以此判断 哪个算法的性能更好
至少在什么情况下更好
当然 也像我们开篇的时候所说的那样
这只是一把尺子
我们这节只告诉你尺子是什么
那么更重要的一个问题就是
尺子怎么用 如何用好这把尺子
有什么样的一些规则 有哪些技巧
那么我们要留待后续课节再向大家作介绍
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)深度优先搜索--作业
-第六章 图--本章测验