目录
1. 初识数据结构
计算机所做的很多事情都是将数据组织起来去操作,这就引出了数据结构与算法。
- 数据结构:研究数据组织,计算机存储、组织数据的方式。
- 算法:计算过程,将输入转换为输出。
- 通俗的讲,数据结构就是数据,算法就是操作。比如:水就是数据结构,而烧水就是算法。
2. 复杂度
一个特定问题有多种解决方案,而如何比较这些解决方案的好坏,这就引出了复杂度的概念。
-
复杂度:衡量算法好坏的标杆
-
分类:时间复杂度、空间复杂度
-
-
2.1 时间复杂度
算法中基本操作的执行次数称为时间复杂度,主要衡量一个算法的运行速度。
时间复杂度不是绝对意义上的快慢;而是随着数据规模的变化,运行时间的变化趋势。
-
2.1.1 时间复杂度衡量依据
-
时间复杂度不依据程序运行时间(绝对时间)来衡量,因为
-
事后衡量:运行出结果才能比较
-
影响因素过多
-
-
时间复杂度的衡量依据算法运行的指令个数F(n),n -> 数据规模
-
CPU主频:单位时间内运行的指令数
-
CPU主频基本固定 -> 可以将算法运行指令数和数据规模的关系 F(n)作为时间复杂度的衡量依据
-
-
- 2.1.2 大O渐进表示法
-
在计算时间复杂度的时候,我们不需要知道精确地执行次数。这就引出了大O渐进表示法。
-
大O渐进表示法
-
O(F(n))
-
只保留最高次项
-
最高次项系数取1
-
-
-
-
2.1.3 运行情况
- 最好情况
- 任意输入的最小运行次数
- 平均情况
- 任意输入的期望运行次数
- 最坏情况
- 任意情况的最大运行次数
- 一般计算时间复杂度关注的是最坏情况
- 最好情况
-
2.1.4 常见时间复杂度
-
从小到大:O(1) < O(log(n)) < O(n) < O(n*log(n)) < O(n²)
-
eg:求斐波那契数的时间复杂度
2+2^1+2^2+....+2^n -> O(2ⁿ)
-
2.1.5 举例
- O(1)
- 获取数组下标
- O(log(n))
- 二分查找、与二叉树高度有关的计算
- O(n)
- 遍历查找、顺序表头插与尾插、链表的下标访问、二叉树的遍历
- O(n*log(n))
- 堆排序、快速排序、归并排序
- O(n²)
- 冒泡排序、插入排序、选择排序
- O(1)
- 2.1.6 利用时间复杂度估算算法耗时
- O(2^n) n=100
- 步骤
- 1. 了解计算机的CPU主频 3G
- 2. 计算
- 3G=3*10^9 每秒执行指令条数
- 2^100 / 3*10^9 ≈ 10^20s -> 需要的秒数
2.2 空间复杂度
空间复杂度主要衡量一个算法所需的额外内存
- 2.2.1 大O渐进表示法
- 数据规模是n的情况下
- 额外使用的空间大小(不考虑输入/输出中使用的空间)
- 常见形式
- 数组的开辟
- eg:int[] array=new int[n²] -> O(n²)
- 递归函数
- eg:斐波那契数 -> 求最长边(用做梦举例,一次只能做一场梦,当一场梦做完后,所用内存就释放了,下一场梦就会继续使用内存) -> O(n)
- 数组的开辟
- 数据规模是n的情况下