算法导论 阅读进度

第一部分 基础知识

第一章 计算中算法的角色 Done

1.1 算法

输入与输出

算法可以解决哪些问题

数据结构

技术

一些比较难的问题

1.2 作为一种技术的算法

效率

算法和其他技术

第二章 算法入门 Done

2.1 插入排序

伪代码如下:

INSERTION_SORT(A)

for j = 2 to length[A]

do key = A[j]

i = j-1

// 将其与已经排好序的数组进行挨个比较

while i>0 and A[i] > key

do A[i+1] = A[i]

i = i-1

A[i+1] = key

原理

其实就是在每次进入一个元素key后,将其与已经排好序的序列进行比较,如果key值小于序列的第一个值(默认为从小到大排序),那么就表明该key应该置入这个序列当中,并且将比较过的元素自动向后移动,以腾出空间放置key。最后将key值置入空位中。

现实中就是在接牌时,插入和调整扑克牌顺序的问题了,算法复杂度为O(n^2)

插入排序采用的是增量方法(incremental),采用分治法的合并排序时间复杂度为O(nlgn)

分治法

- 分解

- 解决

- 合并

主要在于合并算法MERGE(A, p, q, r)

伪代码如下:

MERGE(A, p, q, r)

n1 = q-p+1

n2 = r-q

for i = 1 to n1

do L[i] = A[p+i-1]

for j = 1 to n2

do R[j] = A[q+j]

L[n1+1] = -oo

R[n2+1] = -oo

i = j = 1

for k = p to r

do if L[i] <= R[j]

then A[k] = L[i]

i = i+1

else

A[k] = R[j]

j = j+1

原理

首先将输入数组分割,然后在对分割后的数组进行一一比较,如果L的元素小,就将其输出至目的数组A,如果R小,则输出R至A.

此时MERGE-SORT算法就清晰了,如果将一个数组通过递归不断将其分割,最终分割为每个数组只有一个元素,那么使用MERGE时,就能够将此二元素排序,然后对4元素排序,然后是8元素....

伪代码如下:

MERGE-SORT(A, p, r)

if p

then q = (p+r)/2

MERGE-SORT(A, p ,q)

MERGE-SORT(A, q+1, r)

MERGE(A, p , q, r)

冒泡排序

伪代码如下:

BUBBLE-SORT(A)

for i = 1 to length[A]

do for j = length[A] downto i+1

do if A[j] < A[j-1]

then exchange A[j], A[j-1]

通过不断交换相邻的两个反序元素达到排序的目的,时间复杂度为O(n^2)

1----n-1

2----n-2

3----n-4

....

n-1----1

1+2+3+4+....+n = n(n+1)/2,所以时间复杂度为O(n^2)

第三章 函数的增长 Done

第四章 递归 Done

递归式 T(n) = aT(n/b) + f(n), 其中a>=1, b>1, f(n) 是给定函数

4.1 代换法

猜测解的形式

用数学归纳法找出真正有效的常数

4.2 递归树方法

仔细画出递归树

4.3 主方法

是求解递归式T(n)的食谱方法。

主方法依赖于定理4.1主定理 设a>=1 和 b >1为常数,设f(n)为一函数,T(n)由递归式

T(n) = aT(n/b) + f(n)

对非负整数定义,其中n/b 指上顶或者下底,那么T(n)可能有如下的渐进界

...

主要是针对f(n),a,b等值。

第五章 概率分析与随机化算法

5.1 雇用问题

概率分析,随机算法。

使用概率分布预测输入值的分布,以此来帮助分析算法平均情况行为的。

5.2 指示器随机变量

I(A) = 1,如果A发生的话;0,如果A不发生的话。

5.3 随机算法

无法得到输入分布,考虑使用随机算法。

随机排列数组

许多随机算法通过排列给定的输入数组来使输入随机化。

一个常用方法是为每个数组元素A[i]赋一个随机的优先级P[i],然后按照优先级对数组进行排序,过程PERMUTE-BY-SORT,花费O(nlgn)

原地排列给定的数组,过程RANDOMIZE-IN-PLACE花费O(n)

5.4 进一步使用

1 生日悖论

一个房间的人数需要达到多少,使得两个人生日相同的机会达到50%?分析所有人生日互不相同的概率,其补就为至少两人生日相同。

因此 Pr{Bk} = 1(n-1/n)(n-2/n)(n-3/n)....(n-k+1/n)=1(1-1/n)*(1-2/n)...(1-(k-1)/n)

最后分析得出至少23人在一个房间里,概率就能够为1/2。火星为38个人

2 球与盒子

第二部分 排序和顺序统计学. Done

第六章 堆排序 Done

二叉堆数据结构可以被视为一颗完全二叉树。树的每一层都是被填满的,最后一层可能除外。

父节点

PARENT(i)

return [i/2]

LEFT(i)

return 2i

RIGHT(i)

return 2i+1

有两种:最大堆和最小堆,在这两种堆中,节点内的数组都要满足堆特性,在最大堆中,除了根以外的每个节点,有

A[PARENT(i)] >= A[i]

根元素为最大值。

最小堆刚好相反。

MAX-HEAPIFY. 保持堆的性质,最大堆性质,根或者子根都是树最大元素,O(lgn)

对A[i]的这颗字数执行最大堆化。

算法如下:

MAX-HEAPIFY( A, i )

l = LEFT(A[i])

r = RIGHT(A[i]

If l <= heap-size(A) and A[l] > A[i]

then largest = l

else largest = i

If r <= heap-size(A) and A[r] > A[largest]

then largest = r

If largest != i

then exchange(A[i], A[largest])

MAX-HEAPIFY(A, largest)

建堆 Build-MAX-HEAP, 对每一颗非叶子节点树执行最大堆化,直至根元素。

自n/2 处开始递减,循环执行Max-HEAPIFY,运行时间的界为O(n)

BUILD-MAX-HEAP(A)

heap-size[A] = length[A]

for i = length[A]/2 downto 1

do MAX-HEAPIFY(A, i)

堆排序 HEAPSORT 自叶节点向跟元素递减,交换跟元素和叶节点,接着调用MAX-HEAPIFY, 保持该子树的最大堆性质,即可完成节点自小到大排序,时间复杂度为O(nlgn)

原理

每次都将最大的根元素换至末尾的叶节点,这一操作能够将最大元素调到最后,并且排除出堆,然后再一次构造最大堆,次最大元素又被调节到根元素位置,然后再一次将其换至叶节点,这样,不断循环,就能够将元素在数组中从小到大排列。

HEAPSORT(A)

BUILD_MAX_HEAP(A)

for i = length[A] downto 2

do exchange(A[1], A[i])

heap-size[A] = heap-size[A] - 1

MAX-HEAPIFY(A,1)

最大优先级队列,最小优先级队列的应用如图所示。

第七章 快速排序 Done

QUICKSORT(A,p, r)

If p < r

Then q = PARTITION(A, p, r )

QUICKSORT(A, p, q-1)

QUICKSORT(A, q+1, r)

最初调用时,QUICKSORT(A, 1, length(A) )

其中PARTITION(A, q, r )算法如下

x = A[r]

i = p-1

For j = p to r-1

Do If A[j] <= x

Then i += 1

Exchange(A[i], A[j])

Exchange(A[i+1], A[r])

Return i + 1

分区算法 不断将数组分为四个区:

- 第一区 小于 x的区间 A[p, i]

- 第二区 大于x的区间 A[i+1, j]

- 第三区间 尚未比较的区间 A[j+1, r-1]

- 第四区间 主元 A[r]

每一次运行都是O(n)

总共需要递归调用O(log n),因此算法时间复杂度为O(n log n)

有时我们需要对样本加入一些随机化数据,以便对于所有输入,都能得到较好的平均性能,因此,采用随机选择主元的快速排序随机化版本。

主要是对分区操作进行修改

RAMDOMIZED-PARTITION(A, p, r)

i = random(p, r)

Exchange(i , r)

Return PARTITION(A, p, r)

新的排序算法修改如下:

RANDOMIZED-QUICKSORT(A, p, r )

If p < r

then q = RANDOMIZED-PARTITION(A, p, r)

RANDOMIZED-QUICKSORT(A, p, q-1)

RANDOMIZED-QUICKSORT(A, q+1, r)

第八章 线性时间排序(即时间复杂度为O(n)) Done

合并排序和堆排序在最坏情况下,达到上界O(nlogn),快速排序在平均情况下达到此上界,最坏O(n^2)

比较排序,非比较排序

8.1 排序算法的时间的下界

比较排序可以抽象为决策树模型,比如三个值的比较决策结果又3!= 6

定理8.1 任意一个比较排序的算法在最坏情况下,都需要做O(nlgn)次的比较

推论8.2 堆排序和合并排序都是渐进最优的比较排序算法。

8.2 计数排序**

比较有趣的一个排序算法,使用三个数组空间A,B,C。

统计各个值出现的次数.

C[A[j]] = C[A[j]] +1

可见对于C的空间要求将会比较大,只适用于数值比较小的空间。

这样的排序将会导致各个值A[j]的出现次数按照A[j]值的大小在C中依次由小到大排列。然后计算出C中每个值之前出现多少个值,进而计算出该值所占的位置。

算法如下:

COUNTING-SORT(A, B, k)

for i=0 to k

do C[i] = 0

// 计算A[i] 各个值出现的次数

for j=1 to lenght[A]

do C[A[j]] = C[A[j]]+1

// 计算小于或者等于C[i]值出现的次数

for i=1 to k

do C[i] = C[i]+C[i-1]

// 将A[j]的值按照出现的位置置入B中,并将该值的出现次数减一,使与之相同的值自动排在A[j]的前一个位置

for j = length[A] downto 1

do B[C[A[j]]] = A[j]

C[A[j]] = C[A[j]]-1

该算法很绕,但比较稳定,运行时间为O(n)

8.3 基数排序

基数排序是对具有多个关键字域的记录进行排序,比如年月日。

RADIX-SORT(A,d)

for i = 1 to d

do use a stable sort to sort array A to digit i

可以将一个32位的字视为4个8位的数字,于是就可以将k 缩小至255,数位d变为4.

同样的,利用计数排序作为中间稳定排序的基数排序不是原地排序,占用空间较大。尽管基数排序执行的遍数可能比快速排序少,但每一遍所需的时间要长得多。因此一般还是使用快排,因为快排能够有效的利用硬件缓存,同时也是个原地排序。

8.3 桶排序

输入需要符合均匀分布,即可以以线性时间O(n)运行。计数排序的假设输入由小范围内整数构成,而桶排序假设输入由一个随机过程产生,该过程均匀分布在区间(0,1]

算法

BUCKET-SORT(A)

n = length(A)

for i = 1 to n

do insert A[i] into list B[nA[i]]

for i = 0 to n-1

do sort list B[i] with insertion sort

concatenate the lists B[0],B[1],....

B[n-1] together in order

第九章 中位数和顺序统计学 Done

约定

取下中位数

本章讨论从一个由n个不同数值构成的集合中选择第i个顺序统计量的问题。选择问题的定义如下:

输入:一个包含n个不同的数的集合A和一个数i, 1=

输出: 元素x属于A,它恰大于A中其他的i-1个元素。

最大值和最小值

比如MINIMUM(A)

min = A[1]

for i = 2 to length[A]

do if min > A[i]

min = A[i]

return min

通过n-1比较得出,时间复杂度为O(n)

最大值也是如此。

同时计算最大值和最小值,如使用独立比较需要比较2(n-1)次。

可通过每次输入一对数据,然后将其中大的于最大值比较,小的与最小值比较,每个元素比较三次,但只需运行n/2次,所以总的比较次数是3(n/2)次。

9.2 以期望线性时间做选择

使用RANDOMIZED-SELECT 算法,以第七章快速排序算法为模型,也是对输入数组进行划分,但只处理划分的一边,该边通过与需要选择的位计算而出,期望运行时间为O(n)

RANDOMIZED-SELECT算法利用RADOMIZED-PARTITION程序,返回数组A[p..r]中第i小的元素

RANDOMIZED-SELECT(A, p, r, i)

if p = r

then return A[p]

q = RANDOMIZED-PARTITION(A, p, r)

k = q - p + 1

if i = k

then return A[q]

elseif i < k

then return RANDOMIZED-SELECT(A, p, q-1, i)

//注意i的位置将会做相应的调整,i始终只是相对位置,而q,r都是指在整个数组中的位置

//因此在比较i和k的位置时,是通过计算k的相对位置来与i比较的。

else return RANDOMIZED-SELECT(A, q+1, r, i-k)

按照我的理解,似乎不需要使用i的相对位置,原始位置应该就可以,感觉上没有限制。

结论,在平均情况下,任何顺序统计量特别是中位数,都可以在线性时间内O(n)得到。

9.3 最坏情况线性时间的选择

最坏情况运行时间为O(n)的SELECT算法。采用快速排序的确定性划分算法PARTITION,并做了相应的修改。

- 将输入数组划分为n/5个组,每组5个

- 寻找n/5个组中的每一组中位数,首先对每组中的元素进行插入排序(插入排序在元素数量较小的情况下有着O(n)的复杂度)然后从排序过的数组中选出中位数。

- 在第二步中选出的中位数,递归调用SELECT选出一个中位数x

- 利用修改过的PARTITION过程,按照中位数的中位数x,对输入数组进行划分,让k比划分地区的元素数目多1,所以x就是第k小元素,并且有n-k个元素在划分的高区。

- 如果i = k ,则返回x,否则,如果ik, 则在高区递归调用寻找第(i-k)个最小元素。

本章结论

本章中选择算法之所以具有线性时间,是因为这些算法并没有进行排序。线程时间的行为并不是因为对输入做假设所得到的结果。在比较模型中,即使是在平均情况下,排序仍然需要O(nlgn)的时间,所以从渐进意义上来看,排序和索引方法的效率是不高的。

第三部分 数据结构

第十章 基本数据结构. Done

第十一章 散列表. Done

第十二章 二叉查找树. Done

第十三章 红黑树. Undone

第八部分 附录:数学基础知识

A. 求和. Done

B. 集合等离散数学结构. Done

集合

关系

函数

自由树

有根树和有序树

二叉树和位置树

C. 计数和概率. Undone

C.1 计数

在有限集合S上构造一个长度为k的串称为K串。直观上,为了在n元集上构造一个k串,有n种方法选择第一个元素,同样地,也有N种方法选择第二个元素,这样一次进行K次,从而K串的数目为nnn*...n = n^k.

最形象的就是车牌号了。

排列

有限集S的排列是S中所有元素的有序序列,且每个元素仅出现一次。一个N元集的集合有n!种排列,第一个元素有n种选择,第二个有n-1种选择,第三个有n-2种选择...

集合S的k排列是S中k个元素的有序排列,且每个元素出现一次。因此N元集合的K排列数目是

n(n-1)(n-2)(n-3)(n-4)...(n-k+1) = n!/(n-k)!

组合

n元集的K组合就是S的k子集,n元集的k组合的数目可以用排列的数目来表示,对每个k组合,它的元素恰好有k!中排列,每个都是n元集的一个不同的k排列。因此,n元集的k组合数目是其k排列的数目除以k!。这个数量为

n!/(k!(n-k)!)

组合与排列的区别是,组合中k元祖是无序的,而排列是有序的,意味着组合的元祖对应着k!种不同的排列元祖。

因此在计算时需要除去每个元祖的其他的有序排列。

二项式系数

二项式界

下界

= n!/k!(n-k)! 展开>= (n/k)^k

再利用斯特林近似式得上界

<= n^k/k! <= (en/k)^k

C.2 概率

条件概率Pr{A|B} 读作在事件B发生的条件下,事件A发生的概率

Pr{A|B} = Pr{A交B}/ Pr{B}

A交B是时间A发生,B也发生的事件,因此可以认为这是B中的一个基本事件,因此该事件占整个B事件的概率就是Pr{A交B}/ Pr{N},也即Pr{A|B}

如果Pr{A交B} = Pr{A} Pr{B},则称连个事件独立。

贝叶斯定理

Pr{A交B} = Pr{B} Pr{A|B} = Pr{A} Pr{B|A}

通过交换律,可得如下贝叶斯定理

Pr{A|B} = Pr{A} Pr{B|A}/Pr{B}

C.3 离散随机变量

随机变量X的概率密度函数

f(x) = Pr{X=x}

随机变量的期望值

E[X] = ∑xPr{X=x}

方差

Var[X] = E[(X-E[X]^2)]

= E[X^2]-E^2[X]

C.4 几何分布与二项分布

几何分布

假设进行一系列的伯努利实验,每次实验成功的概率是P,失败的概率是q=1-p,在取得一次成功前要进行多少次实验?因为在取得一次成功前有k-1次失败,从而有

Pr{X=k} = q^(k-1)p

期望 1/p

二项分布

因为有(n k) 种方法从n次实验中选取k次成功的试验,且每次发生的概率是p^k*q^(n-k)

Pr{X=k} = (n k)p^k*q^(n-k)

期望E[X] = np, 方差 Var[X] = npq

发自我的 iPad

算法导论中C语言代码,算法导论-学习笔记与进度相关推荐

  1. 《统计学习导论》R语言代码整理

    <统计学习导论>R语言代码整理 一.特殊函数 二.基本函数 三.画图 一些函数 一些参数 type pch (plotting character) lty(line types) 特定问 ...

  2. 操作系统实验:页面置换算法的模拟实现及命中率对比(学习笔记)

    操作系统实验:页面置换算法的模拟实现及命中率对比(学习笔记) 题目要求 输入要求 输出要求 编程平台 实验成果 开始模拟 错误输入 退出程序 代码实现 抽象数据类型定义 指令地址流生成 指令地址流到页 ...

  3. R语言与函数估计学习笔记(函数模型的参数估计)

    R语言与函数估计学习笔记 毫无疑问,函数估计是一个比参数估计要复杂得多的问题,当然也是一个有趣的多的问题.这个问题在模型未知的实验设计的建模中十分的常见,也是我正在学习的内容的一部分. 关于函数估计我 ...

  4. c语言编程实例解析精粹,C语言实例解析精粹学习笔记——35(报数游戏)

    实例35: 设由n个人站成一圈,分别被编号1,2,3,4,--,n.第一个人从1开始报数,每报数位m的人被从圈中推测,其后的人再次从1开始报数,重复上述过程,直至所有人都从圈中退出. 实例解析: 用链 ...

  5. R语言与抽样技术学习笔记(Jackknife)

    R语言与抽样技术学习笔记(Randomize,Jackknife,bootstrap) Jackknife算法 Jackknife的想法在我很早的一篇博客<R语言与点估计学习笔记(刀切法与最小二 ...

  6. c语言/c++转Java学习笔记---基础问题

    c语言/c++转Java学习笔记---基础问题 1.java注释 2.数组的定义和使用 定义 使用 3.类 4.this 的使用 5.继承 6.super的使用 7.包 8.修饰符 成员的访问控制符( ...

  7. python面向对象编程中方法和属性_Python面向对象编程中关于类和方法的学习笔记...

    Python面向对象编程中关于类和方法的学习笔记 类与类方法是面向对象的编程语言中必不可少的特性,本文总结了Python面向对象编程中关于类和方法的学习笔记,需要的朋友可以参考下 类和实例 pytho ...

  8. Asp.Net 中Report Service (RDLC)动态绑定数据-学习笔记

    Asp.Net 中Report Service (RDLC)动态绑定数据-学习笔记 1)托拽ReportViewer控件到aspx页面,此时,系统会自动添加相关引用,修改Web.config设置: 2 ...

  9. Java中如何创建自定义的注解学习笔记(MD版)

    概要 Java中如何创建自定义的注解学习笔记(MD版). 博客 博客地址:IT老兵驿站. 前言 记得这篇笔记还是在泉州的龙玲酒店记录的,是一个周六的晚上,坐飞机从上海到泉州,从笔记中能勾起一些旅游的回 ...

最新文章

  1. signature=65a5d6b0ac441e09ae68e9bbee76cba1,Bortezomib
  2. 前端基础——day1
  3. 移动前端开发基础与优化
  4. vba 判断控件有无_6小时,写了一篇适合Excel小白学的VBA入门教程
  5. 2-36进制,可以任意进制互转的类
  6. 华为mate8对flex的支持
  7. iOS 相册图片选择器
  8. 吴恩达机器学习cs229一二节总结
  9. Landsat 数据其中 Collection 1/2 、Level 1/2、Tier 1/2的区别
  10. 2021-03-27
  11. 什么是三网合一短信接口呢
  12. 28款GitHub最流行的开源机器学习项目,推荐GitHub上10 个开源深度学习框架
  13. 【matlab小笔记】
  14. 关于Spring中的ClassPath
  15. 项目难于管理的根本原因在于项目的”VUCA”特性
  16. 廉价交换机走俏的原因以及使用中的风险
  17. 关于爬取arXiv论坛论文并按照论文主题进行分类的办法
  18. python中输出手机话费_用Python生成柱状图、折线图、饼状图来统计自己的手机话费...
  19. 输入9V-12V输出8.4V1.5A双节锂电池充电芯片
  20. 虚拟内存架设服务器客户端,怎么在服务器上开虚拟内存

热门文章

  1. JavaScript最全的10种跨域共享的方法
  2. Javascript中闭包的作用域链
  3. 人生抉择之-创业记录片(一)
  4. 开发环境中实现Lombok消除Java冗余
  5. Linux和Windows文件系统
  6. CentOS 7最小化安装步骤
  7. 广域网智能流量调度—Vecloud
  8. 广域网一般采用什么网络拓扑结构?—Vecloud
  9. OSI七层模型中每层的协议及网络设备—Vecloud微云
  10. jQuery获取或设置元素的宽度和高度