目录
3.1.2嵌套代码的时间复杂度等于嵌套内外的代码的时间复杂度的乘积
数据结构是一门研究非数值计算的程序设计中,计算机的操作对象以及它们之间的关系和操作的学科。
1.数据结构的种类
1.1逻辑结构
逻辑结构描述了数据元素之间的逻辑关系,与数据的存储无关,是从具体问题抽象出来的数学模型。
1.1.1集合结构
集合结构中的数据元素是并列关系。(如一个集合中各个元素之间的关系)
1.1.2线性结构
线性结构中的数据元素之间是一对一的关系。(如线性表、栈、队列、串)
1.1.3树形结构
树形结构中的数据元素之间存在一对多的层次关系(金字塔状)。
1.1.4图形结构
图形结构的数据元素是多对多的关系。(网状)
例如地图导航里,就是将各个地点视作一个个点,点与点之间的路径就是线,他们和在一起组成了一个图形结构。
1.2物理结构(存储结构)
数据的物理结构研究的就是如何把数据元素存储到计算机的存储器中,是数据结构在计算机中的表示。
1.2.1顺序存储结构
用一组连续的存储单元,按照数据元素的顺序依次存储,数据元素之间的逻辑关系由元素的存储位置来表示。(如数组)
1.2.2链式存储结构
用一组任意的存储单元存储数据元素(链表),数据元素之间的逻辑关系用指针来表示。
1.2.3索引存储结构
(图源第01周c--1.2基本概念和术语1_哔哩哔哩_bilibili)
1.2.4散列存储结构
(图源同上)
1.3逻辑结构与存储结构的关系
逻辑结构是数据结构的抽象;存储结构是数据结构的实现。
存储结构是逻辑关系的映像与元素本身的映像。
2.数据类型和抽象数据类型
2.1数据类型
定义:数据类型是一组性质相同的值的集合,以及定义域这个值集合上的一组操作的总称。
即:数据类型 = 性质相同的值的集合(如整型数)+ 值集合上的一组操作(如+-*/%)
2.2抽象数据类型(ADT)
抽象意思是,将一组具体事物所具有的相同特征、本质属性和关系抽出,舍弃非共有的特征、属性和关系的思维过程。
抽象数据类型是指,一个数学模型以及定义在此数学模型上的一组操作。
即:ADT = 数学模型 + 数学模型上的一组操作
其中,数学模型(即逻辑结构)是由用户从问题中抽象出来的,再根据实际需要确定这个数学模型上进行的操作(这种操作不局限于四则运算,可能是抽象的运算)。
ADT的形式定义:
(图源同上)
ADT的定义格式:
(图源同上)
其中,基本操作的定义格式为:
抽象数据类型定义举例:circle定义
概念小结:
3.时间复杂度分析
3.1分析方法
3.1.1只关注循环执行次数最多的一段代码
因为时间复杂度全称是渐进式时间复杂度,即用来表示当 n 的值(即数据量)不断增大时,所需消耗的时间的长短。可以假设每一行有效代码的运行时间都是 t ,则在一段只有一个循环的代码中,运行所需要的时间长短可以表示为2*n*t + C(C是常数)。也就是说随着数据的增加,真正影响时间的其实只是循环里的内容,C可以忽略不记,因此最终的时间复杂度是 O(n) 。同理,在一段只有2个循环的代码中,所需的时间长短可以表示为 n^2 * t+ n*t + C,当n趋于无穷时,n也可以省略,所以最终的时间复杂度是O(n^2)。总结来说,就是只需关注循环次数最多的一段代码来计算时间复杂度即可。
#include<iostream>
using namespace std;
int main()
{
int n=0,sum=0; //耗时t
cin>>n; //耗时t
for(int i=1;i<=n;i++) //耗时 t*n
{
sum+=i; //耗时 t*n
}
cout<<sum; //耗时t
return 0; //耗时t
}
3.1.2嵌套代码的时间复杂度等于嵌套内外的代码的时间复杂度的乘积
例如在一个for循环n次的函数里嵌套了另一个for循环n次的函数,那么这个函数总的时间复杂度就是O(n^2)
3.2常见的时间复杂度
一般来说,复杂度达到O(n^2)的代码在实际使用时就需要慎重考虑,而复杂度大于O(n^2)的代码一般很少使用。
当然,一个函数并不总是只有一个参数,也有多个未知参数同时存在的情况,这时就会出现O(m+n)和O(m * n)之类的算法复杂度。
3.3计算时间复杂度实例
计算时间复杂度的关键是要找出执行次数x与n的关系,并表示成n的函数。
(图源同上)
4.递归
适合使用递归的问题需要具备三个条件:
(图源 1-003-什么是递归_哔哩哔哩_bilibili)
递归使用注意事项:使用递归时必须设定退出条件,比如设定递归次数为n,每次递归后就让n++,直到n>m之后就推出递归。
递归弊端:
1、空间复杂度高;
2、容易堆栈溢出;
3、容易重复计算;