标签:wap ati div 运行 针对 衡量 高中 基础上 swa
我们先来观察几个简单的四则运算:
3 + 1 = 2
23 + 23 = 46
2 + 4 = 6
上面几个式子有什么相似之处呢?
很显然它们的统一特征就是“求和”。我们找一个符号来抽象表示“这件事情”,比如说用 sum(a, b) 表示“求和”,
这样的话我们可以推出 sum(3, 1) = 2
sum(23, 23) = 46,
“ + ”只不过是个符号而已!
再比如我们需要把一些数组从小到大到排序。
例如说 1 3 2 ,很容易得到 1 2 3
再比如 1 4 3 ,很容易得到 1 3 4
我们同样可以用一个符号来抽象表示这件事情, sort(1, 3, 2) 。 (sort 是英语中的排序)
那我现在问你,你到底是如何把 1 3 2 从小到大到排序的呢?
按照普通高中生的思维,一般都会说:这还用想?#@X 把 3 和 2 调换就可以了。。
好吧 那我让你将 1729 237 9123 263 12 123 2813 123 213 123 321 312 3... 从小到大到排序你会怎么做呢?
▉▊▋▌▍▎▉▊▋▌▍▎▏█▇ ▆ ▅ ▄ ▃ ▂ ▂
▏█▇ 请稍微思考一会儿。 ▌▍▎▇ ▆
▍▎▏▉▊▍▎▏▉▊▋▌▍▎▏▌▍▎█▌▍▎▌▍
是不是发现有特别多的方法?例如说你可以把最小的挑出来,然后再去找次小的、又或者可以按照排队的方法,把大的往后换...
当然,在我们软件开发的过程中要做的事情通常不是排序那么简单。
例如说一个非常简单的例子。。我希望你让计算机识别某张图片中的数字。。同样的,我们可以像 sum() 、sort() 一样把它抽象为 f(a.jpg) , f 只是个记号!
好吧,对于这个问题,我想非专业人员并不是很快可以知道该怎么做的。。。
我们把类似于 sum() 、sort() 、f(a.jpg) 的玩意儿叫做 “ 算法 ” ,我希望你可以建立一个更直观的理解。
大多数情况都不需要我们从头到尾亲自去设计一个算法,也就是你不需要去亲自弄清楚怎么样去识别图片中的数字。
更多时候,我们是作为一个算法的使用者,“识别数字”往往也只是软件功能的一小部分,
我们做得更多的事情是“分析算法”,然后拿来用:
要分析一个算法,首先需要我们能够看懂算法(),其次是能够甄别算法的效率。
WELL
我们怎样判断一个算法的效率呢?严格来讲一个算法的快慢相关于其具体的运行环境。
如果是真实的场景的话,肯定是要基于具体条件分析的。
但是从应用的角度,我们一般假设算法都运行在相同的环境下(诸如硬件条件、内存之类的),在此基础上去衡量算法的运行时间,这个运行时间对于不同的输入显然也不是一成不变的,排序 1 3 2 显然比排序 1729 237 9123 263 12 123 2813 123 213 123 321 312 3...快得多。
倘若赤裸裸的分析一个算法的话,运行时间指的是算法运行的步数哦!!!一般呈现这样的关系:运行时间相关于输入规模和输入内容,
(当然,存在对于特定输入却有不同运行时间的状况,暂且不提)
通常认为,一个算法的增长量级越低就越有效,例如说n^2 相对于 nlogn 显得很笨重!
具体怎么算参考算法导论。
扯那么多,我其实是想说:分析算法特别.特别.特别重要!!!你可以不知道各种各样的算法的具体实现(这没必要,通常也不现实!),但是它们有什么用、效率怎么样总应该要懂吧?而搞懂这一切的诀窍、捷径就是去分析.大量.算法,当然不是叫你把每行代码都搞得很清楚(那是算法研究员搞的。。),重点是上面的两点!—— 有什么用、效率怎么样
// 以上观点偏主观,所以。。仁者见仁吧。:p
2.2-1
theta n^3
2.2-2
SELECTION-SORT(A) for i = 1 to A.length-1 for j = i+1 to A.length if A[i] > A[j] swap(A[i], A[j])
维持的循环不变式是 A[1..i] 按序排列(从小到大),
非形式化,不太严谨地证明一下:
初始化:对于单个元素 A[1],显然成立。
保持:我们假设在 i = n 时循环不变式成立,那么当 i = n + 1 时,A[i] 将会和 A[i+1] ~ A[A.length] 中的每个元素进行比较,最终 A[i] 将取得它们中的最小值,事实上它就是在整个序列中次小于 A[i-1] 的那个数(因为每次迭代总会拿到剩余队列的最小值,因此“下一次”只能拿到仅次于“上次”的最小值),故 A[1..i] 保持循环不变式。
终止:当 i = A.length 时迭代结束,根据上面的证明 A[1..A.length-1] 已确保有序, A[A.length] 是经过 A.length - 1 次比较后剩下的次次次..(省略 A.length - 4 个次).次最小数,也就是序列中的最大数,因此 A[1.. A.length] 按序排列,故算法正确。
算法的运行时间 T(n) = c1*(n-1) + c2*(n-1+1)*n / 2 + c3*(n-1+1)*n / 2 + c4*(n-1+1)*n / 2
最佳状况是数组已经有序(c4 取 0),最坏情况是数组逆序(如上式),不过两者增长量级是相同的,都是 theta n^2 。
2.2-3
平均需要检查 n / 2 个元素,最坏情况需要检查 n 个。
平均情况和最坏情况的增长量级都是 theta n
SEARCH(v, A) for i = 1 to A.length c1 tn if A[i] == v c2 tn return i c3 1 or 0 return NIL c4 1 or 0
T(n) = c1*tn + c2*tn + c3 + c4
代入 n (最坏)或者 n/2 (平均),忽略常数,结果都是 theta n
2.2-4
针对特殊情况进行测试,如果符合的话就直接给出预先计算好的答案。
就是增加常数时间能跑完的代码,用于覆盖一些特例,减少无所谓的循环。
下面是网上找的参考答案:
// 以上纯属个人观点,若有什么不恰当(或者给人产生误导)之处,麻烦指正哦 ~~
算法导论(第三版)练习 2.2-1 ~ 2.2-4 ( feat. 算法杂谈)
标签:wap ati div 运行 针对 衡量 高中 基础上 swa
原文地址:http://www.cnblogs.com/xkxf/p/7659961.html