数据结构与算法——学习整理记录
Posted elinuxboy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法——学习整理记录相关的知识,希望对你有一定的参考价值。
===注:此文由本人结合网上资源整理总结而来,仅代表个人的学习与理解,如有错漏,欢迎指正!===
# 1. 数据结构
## 1.1 数据结构是什么?
数据结构,直白地理解,就是研究数据的逻辑关系与存储方式的一门学科。
可以简单的分为:数据的逻辑结构(逻辑关系)和数据的存储结构(物理结构)。
它是以某种形式将数据组织在一起的集合,它不仅存储数据,还支持访问和处理数据的操作。
### 1.1.1 数据的逻辑结构
数据的逻辑结构,简单地理解,就是指的数据之间的逻辑关系。
数据之间的逻辑关系可简单的分为三类:
- 一对一
- 一对多
- 多对多
### 1.1.1 数据的存储结构
数据的存储结构,也就是物理结构,指的是数据在物理存储空间上的存放方式,可以选择集中存放,还是分散存放。
假设要存储大小为 10M 的数据,则集中存放就如图1(a)所示,分散存放就如图1(b)所示。
图1(a) 数据的集中存放
图1(b) 数据的分散存放
## 1.2 为什么要用数据结构?
使用数据结构的目的,即方便对数据的利用和操作。
## 1.3 数据结构有哪些?
根据数据的逻辑结构和存储结构,可以把数据结构分为三大类:
- 第一类:线性表,用于存储具有“一对一”逻辑关系的数据。包括顺序表、链表、栈和队列;
- 第二类:树结构,用于存储具有“一对多”逻辑关系的数据。包括普通树,二叉树,线索二叉树等;
- 第三类:图结构,用于存储具有“多对多”逻辑关系的数据;
## 1.4 如何使用数据结构?
可以通过分析数据之间的逻辑关系来决定使用哪种存储结构,但具体使用顺序存储还是链式存储,还要通过数据的物理结构来决定。
如果选择集中存储,就使用顺序存储结构;反之,就使用链式存储。至于如何选择,主要取决于存储设备的状态以及数据的用途。
数据的用途不同,选择的存储结构也不同。将数据进行集中存储有利于后期对数据进行遍历操作,而分散存储更有利于后期增加或删除数据。因此,如果后期需要对数据进行大量的检索(遍历),就选择集中存储;反之,若后期需要对数据做进一步更新(增加或删除),则选择分散存储。
# 2. 算法
## 2.1 算法是什么:
算法,从表面意思来理解,即解决问题的方法。
算法是为求解一个问题需要遵循的、被清楚指定的简单指令的集合。
在计算机中,算法是指解决方案的准确而完整的描述。
### 2.1.1 算法与程序
算法是解决某个问题的想法、思路;而程序是在心中有算法的前提下编写出来的可以运行的代码。
某种程度上,算法相当于是程序的雏形。
当解决问题时,首先心中要有解决问题的算法,围绕算法编写出程序代码。
## 2.2 算法设计的要求
准确性、健壮性、运行效率(复杂度)
对于一个问题,想出解决的算法,不一定就能解决这个问题。为了避免这种情况的发生,要充分全面地思考问题,尽可能地考虑到所有地可能情况,慎重选择算法(需要在实践中不断地积累经验)。
### 2.2.1 算法的运行效率(复杂度)
算法的运行效率(复杂度)体现在两方面:
- 算法的运行时间。(称为“时间复杂度”)
- 运行算法所需的内存空间大小。(称为“空间复杂度”)
#### 拿时间换空间,用空间换时间
算法的时间复杂度和空间复杂度是可以相互转化的。
比如:谷歌浏览器相比于其他的浏览器,运行速度要快。是因为它占用了更多的内存空间,以空间换取了时间。
## 2.3 一个好算法的标准
在符合算法本身的要求(准确性和健壮性)的基础上,使用算法编写的程序运行的时间短,运行过程中占用的内存空间少,就可以称这个算法是“好算法”。
## 2.4 算法时间复杂度计算
计算一个算法的时间复杂度,不可能把所有的算法都编写出实际的程序出来让计算机跑,这样会做很多无用功,效率太低。实际采用的方法是估算算法的时间复杂度。
程序(C语言)一般由三种结构构成:顺序结构、分支结构和循环结构。顺序结构和分支结构中的每段代码只运行一次;循环结构中的代码的运行时间要看循环的次数。
由于是估算算法的时间复杂度,相比而言,循环结构对算法的执行时间影响更大。所以,算法的时间复杂度,主要看算法中使用到的循环结构中代码循环的次数(称为“频度”)。次数越少,算法的时间复杂度越低。
### 2.4.1 时间复杂度的表示
算法的时间复杂度的表示方式为:
O(频度)
这种表示方式称为大“O”记法。
——注意,是大写的字母O,不是数字0。
例如:
a) ++x; s=0;
b) for (int i=1; i<=n; i++) { ++x; s+=x; }
c) for (int i=1; i<=n; i++) { for (int j=1; i<=n; j++) { ++x; s+=x; } }
上边这个例子中,a 代码的运行了 1 次,b 代码的运行了 n 次,c 代码运行了 n*n 次。
所以使用算法的时间复杂度表示为:
a 的时间复杂度为O(1),b 的时间复杂度为O(n),c 的时间复杂度为为O(n2)。
如果把a、b、c三个例子组成一段程序,那么算法的时间复杂度为O(n2+n+1)。但这么表示是不对的,还需要对n2+n+1进行简化。
简化的过程总结为3步:
- 去掉运行时间中的所有加法常数。(例如 n2+n+1,直接变为 n2+n)
- 只保留最高项。(例如 n2+n 变成 n2)
- 如果最高项存在但是系数不是1,去掉系数。(例如 n2 系数为 1)
所以,最终a、b和c合并而成的代码的时间复杂度为O(n2)。
## 2.5 常用的时间复杂度的排序
列举了几种常见的算法时间复杂度的比较(又小到大):
O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(n2)平方阶 < O(n3)(立方阶) < O(2n) (指数阶)
3. 数据结构与算法关系
可以从分析问题的角度去理清数据结构和算法之间的关系。
通常,每个问题的解决都经过以下两个步骤:
- 第一步:分析问题,从问题中提取出有价值的数据,将其存储;
- 第二步:对存储的数据进行处理,最终得出问题的答案;
数据结构负责解决第一个问题,即数据的存储问题。针对数据不同的逻辑结构和物理结构,可以选出最优的数据存储结构来存储数据。而算法负责为剩下的第二个问题提供解决方案。
总而言之,数据结构用于解决数据存储问题,而算法用于处理和分析数据,它们是完全不同的两类学科。
# 参考
以上是关于数据结构与算法——学习整理记录的主要内容,如果未能解决你的问题,请参考以下文章