数据结构
对计算机内存中的数据的一种安排。
算法
对结构中的数据进行各种处理
应用方面
- 现实世界的数据存储
- 作为程序员的工具
- 关于现实世界的建模
数据结构 | 优点 | 缺点 |
数组 | 插入快(知道下标) | 查找慢,删除慢,大小固定 |
有序数组 | 比无序的数组查找快 | 删除和 插入慢,大小固定 |
栈 | 提供后进先出的存取方法 | 存取其他项很慢 |
队列 | 提供先进先出的存取方法 | 存取其他项很慢 |
链表 | 插入快 删除快 | 查找慢 |
二叉树 | 查找 删除 插入都快(树平衡的情况下) | 删除算法复杂 |
红黑树(平衡树) | 插入 查找 删除 都快 | 算法复杂 |
2-3-4树(平衡树) | 插入 查找 删除 都快 | 算法复杂 |
哈希表 | 插入快,通过关键字存取快 | 删除慢 |
堆 | 插入、删除快,对最大数据项的存取很快 | 对其他项的存取慢 |
图 | 对现实世界建模 | 有些算法慢并且复杂 |
算法效率的度量方法
- 算法采用的策略,方案。
- 编译产生的代码质量
- 问题的输入规模
- 机器执行指令的速度
- 研究算法的复杂度,侧重的是研究算法随着输入规模扩大增长量的一个抽象,而不是精确地定位需要执行多少次。
- 我们不关心编写程序所用的语言是什么,也不关心这些程序将跑在什么样的计算机上,我们只关心它所实现的算法。
- 不计那些循环索引的递增和循环终止条件、变量声明、打印结果等操作。最终,在分析程序的运行时间时,最重要的是把程序看成是独立于设计语言的算法或一系列的步骤。
- 在分析一个算法的运行时间时,重要的是把基本操作的数量和输入模式关联起来。
函数的渐进增长
判断以下两个算法A和算法B哪个更好?
假设两个算法的输入规模都是n,算法A要做2n+3次操作,算法B要做3n+1次操作,哪个更好?
规模 | 算法A1(2n+3) | 算法A2(2n) | 算法B1(3n+1) | 算法B2(3n) |
n=1 | 5 | 2 | 4 | 3 |
n=2 | 7 | 4 | 7 | 6
|
n=3 | 9 | 6 | 10 | 9 |
n=10 | 23 | 20 | 31 | 30 |
n=100 | 203 | 200 | 301 | 300 |
当n=1时,算法A1效率不如算法B1,当n=2时,两者效率相同;当n>2时,A1算法优于B1算法,随着n的继续增加,算法A!比算法B1逐步拉开差距。所以总体上算法A1比算法B1优秀。
函数的渐进增长:给定两个函数f(n)和g(n),如果存在一个整数N,使得对所有的n>N,f(n)总是比g(n)大,那么我们说f(n)的增长渐进快于g(n)。
最高
判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高项)的阶数。
算法时间复杂度:
算法时间复杂度的定义:在进行算法分析时,语 句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。 算法的时间复杂度,也就是算法的时间量度 记作: T(n)= 0(f(n))。它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。
这样用大写O()来体现算法时间复杂度的记法,我们称之为大0记法。一般情况下,随着输入规模n的增大,T(n)增长
最慢的算法为最优算法。
推导大O阶方法
那么如何分析一个算法的时间复杂度呢?即如何推导大O阶呢?我们给大家整理了以下攻略:
一用常数1取代运行时间中的所有加法常数。
一在修改后的运行次数函数中,只保留最高阶项。
—如果最高阶项存在且不是1,则去除与这个项相乘
的常数。
一得到的最后结果就是大O阶。
线性阶
一般含有非嵌套循环涉及线性阶,线性阶就是随着问题规模n的扩大,对应计算次数呈直线增长。
常见的时间复杂度
例子 | 时间复杂度 | |
52634 | O(1) | 常数阶 |
3n+4 | O(n) | 线性阶 |
3n^2+4n+5 | O(n^2) | 平方阶 |
3log(2)n+4 | O(logn) | 对数阶 |
2n+3nlog(2)n+14 | O(nlogn) | nlogn阶 |
n^3+2n^2+4n+6 | O(n^3) | 立方阶 |
2^n | O(2^n) | 指数阶 |
常用的时间复杂度所耗费的时间从小到大依次是: O(1)<O(logn) < O(n) < O(nlogn) <O(n^2) < O(n^3) < O(2^n) < O(n! ) <O(n^n)
最坏情况与平均情况
- 平均运行时间是期望的运行时间。
- 最坏运行时间是一种保证。在应用中,这是一种最重要的需求,通常除非特别指定,我们提到的运行时间都是最坏情况的运行时间。
算法的空间复杂度
算法的空间复杂度通过计算算法所需的存储空间实现,算法的空间复杂度的计算公式记作:S(n)=O(f(n)),其中,n为问题的规模,f(n) 为语句关于n所占存储空间的函数。
通常,我们都是用 时间复杂度”来指运行时间的需求,是用“空间复杂度”指空间需求。
当直接要让我们求“复杂度”时,通常指的是时间复杂度。