目录
一、什么是数据结构
数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的 数据元素的集合。
数据结构关注的是数据的逻辑结构和物理存储结构。
逻辑结构主要描述数据元素之间的关系,比如线性结构(如数组、链表)、树结构(二叉树、B 树等)、图结构等。
物理存储结构则是数据在计算机内存中的实际存储方式,例如顺序存储和链式存储。
数据结构的重要性在于:
- 它能提高数据处理的效率,选择合适的数据结构可以让特定操作更快速地执行。
- 帮助更好地组织和管理大量的数据,使其更易于操作和理解。
- 为算法设计提供基础,不同的数据结构适用于不同的算法。
什么是算法
算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为 输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。
算法具有以下特征:
- 输入项:算法需要有输入或者说初始条件;
- 确定性:算法的每一步必须要有确定的含义,不能有歧义;
- 有穷性:算法在执行有限步骤之后必须结束;
- 输出:算法必须要有一个或多个输出,即与输入有某个特定关系的量;
- 可行性:算法中有待执行的运算和操作必须是可以实现的,能够精确地进行。
算法可大致分为基本算法、数据结构的算法、数论与代数算法、计算几何的算法、图论的算法、动态规划、数值分析、加密算法、排序算法、检索算法、随机化算法、并行算法等。
算法的复杂度
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般 是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。 时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算 机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计 算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
一般算法常见的复杂度如下:
二、时间复杂度
时间复杂度,又称时间复杂性,在计算机科学中,它是一个函数,用来定性描述算法的运行时间。
时间复杂度是一个代表算法输入值的字符串的长度的函数,常用大 O 符号表示,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,即考察输入值大小趋近无穷时的情况。
将算法需要执行的运算次数用输入大小 n 的函数表示,即为 T(n)。为了估算算法需要的运行时间和简化算法分析,便引入了时间复杂度的概念。
常见的时间复杂度量级包括:
- 常数阶 O(1):无论代码执行了多少行,只要没有循环等复杂结构,时间复杂度就都是 O(1)。例如:
- 线性阶 O(n):代码的执行时间与问题规模 n 呈线性关系。例如上述的 for 循环代码。
- 对数阶 O(logN):例如:
- 线性对数阶 O(nlogN):将时间复杂度为 O(logn)的代码循环 N 遍,时间复杂度就是 n * O(logN)。
- 平方阶 O(n^2):例如嵌套循环
- 立方阶 O(n³)、K 次方阶 O(n^k)等。
在分析时间复杂度时,通常遵循以下原则:
- 循环次数最多原则:只需关注循环次数最多的那段代码。
- 加法原则:量级最大的那段代码时间复杂度等于总的时间复杂度。
- 乘法原则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积。
算法的时间复杂度可以帮助我们评估算法的效率,在实际应用中,我们希望选择时间复杂度较低的算法,以提高程序的运行速度和性能。但同时,也需要综合考虑空间复杂度等其他因素,以找到最适合具体问题的解决方案。
三、空间复杂度
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。它是一个算法所需存储空间的函数,记作S(n)=O(f(n)),其中为n问题的规模,f(n)为语句关于的所占存储空间的函数。
常见的空间复杂度有O(1)、O(n)和O(n^2)等:
当算法运行时占用的临时空间不随某一变量n的改变而改变时,即空间复杂度为常量,表示为O(1);
当算法运行时占用的临时空间随n的改变而改变时,空间复杂度即为O(n);
当算法运行时占用的临时空间随n^2的改变而改变时,空间复杂度则为O(n^2,以此类推。
算法的空间复杂度主要考虑在运行过程中为局部变量分配的存储空间的大小,它包括为参数表中形参变量分配的存储空间和为在函数体中定义的局部变量分配的存储空间两个部分。若算法为递归算法,其空间复杂度为递归所使用的堆栈空间的大小,等于一次调用所分配的临时存储空间的大小乘以被调用的次数(即为递归调用的次数加 1,这个 1 表示开始进行的一次非递归调用)。
空间复杂度一般也以数量级的形式给出,用于衡量算法运行时所需额外空间的增长趋势,而不是具体计算占用的存储空间大小。
例如,冒泡排序算法的空间复杂度通常为O(1),因为它在运行过程中只使用了固定数量的额外空间来存储交换标志等少数几个变量;而一些使用递归实现的算法,如计算斐波那契数列的递归算法,其空间复杂度可能为O(n),因为递归调用会在堆栈中占用与输入规模成正比的空间。
在分析算法的优劣时,通常需要同时考虑时间复杂度和空间复杂度。有时为了追求较低的时间复杂度,可能会导致空间复杂度增加;反之,为了降低空间复杂度,可能会使时间复杂度上升。在实际应用中,需要根据具体情况进行权衡和选择。
四、总结
时间复杂度:
- 用于衡量算法运行所需时间随输入规模增长的变化趋势。
- 常见的时间复杂度级别有:O(1)(常数级)、O(n)(线性级)、O(logn)(对数级)、O(nlogn)(线性对数级)、O(n²)(平方级)等。
- 帮助我们评估算法在不同规模输入下的效率,以便选择更高效的算法。
空间复杂度:
- 描述算法在运行过程中所需额外存储空间的大小与输入规模的关系。
- 也有类似的级别划分,如 O(1)(固定额外空间)、O(n)(与输入规模线性相关的额外空间)等。
- 考虑空间复杂度可以避免因占用过多内存而导致程序运行异常或效率低下。
在实际情况中,需要综合考虑时间复杂度和空间复杂度。有时候为了降低时间复杂度可能会适当增加空间复杂度,反之亦然。例如:
- 一些排序算法可能时间复杂度较低,但需要额外较多的空间来辅助排序。
- 某些算法可能空间复杂度低,但运行时间相对较长。
在选择算法时,要根据具体的应用场景和需求进行权衡。如果对运行速度要求极高,可以优先考虑时间复杂度低的算法;如果内存资源有限,则要更关注空间复杂度。总之,要在时间和空间的效率之间找到一个合适的平衡点。