绪论——一文速通
一、数据结构的逻辑结构和存储结构表示方法及关系
这个概念是数据结构的基石,它明确了数据的“抽象形态”和“物理实现”之间的区别与联系。
(1)逻辑结构
-
定义:逻辑结构是指数据元素之间的抽象关系,与数据在计算机中的具体存储方式无关。它就像一张设计蓝图,只关心各个部分之间如何关联。
-
主要类型:
-
集合:数据元素之间除了“同属一个集合”外,没有其他关系。
-
线性结构:数据元素之间存在一对一的先后顺序关系。如:线性表、栈、队列。
-
树形结构:数据元素之间存在一对多的层次关系。如:二叉树、家族族谱。
-
图状结构(或网状结构):数据元素之间存在多对多的任意关系。如:社交网络、地图路径。
-
(2)存储结构(物理结构)
-
定义:存储结构是指逻辑结构在计算机内存中的具体实现方式,即如何用二进制位表示数据元素以及如何安排存储位置来表示数据元素之间的关系。它就像按照蓝图,用砖块和水泥实际盖房子的过程。
-
主要类型:
-
顺序存储:用一组地址连续的存储单元依次存放数据元素。数据间的逻辑关系通过存储位置的相邻关系来体现(如数组)。
-
优点:随机存取,访问元素速度快。
-
缺点:插入、删除操作需要移动大量元素;需要预先分配足够大的连续空间。
-
-
链式存储:不要求连续的存储空间。每个数据元素(节点)不仅包含数据本身,还包含一个或多个指向其他节点的指针,通过指针来表示数据元素间的逻辑关系。
-
优点:插入、删除操作灵活,只需修改指针,无需移动元素;空间利用率高,按需申请。
-
缺点:不能随机存取,必须从头开始顺序查找;指针需要占用额外空间。
-
-
(3)关系
-
区别:
-
逻辑结构是面向问题的,是抽象的、独立的。
-
存储结构是面向计算机的,是具体的、依赖的。
-
-
联系:
-
逻辑结构是存储结构的设计依据和基础。我们首先要根据问题的需求确定数据的逻辑结构(比如,需要快速访问就用线性表,需要表示层级就用树)。
-
存储结构是逻辑结构在计算机中的物理实现。同一种逻辑结构可以采用不同的存储结构来实现。
-
例如:“线性表”这种逻辑结构,既可以用“顺序存储”(即数组)来实现,也可以用“链式存储”(即链表)来实现。
-
-
存储结构的选择会影响算法的效率。选择不同的存储结构,会导致实现同一操作的算法在性能上产生巨大差异。
-
二、算法五个要素的确切含义
一个算法应该是一个明确的、可执行的计算步骤序列。它必须具备以下五个基本特征(或称为要素):
-
有穷性
-
含义:一个算法必须总是在执行有限步之后结束,且每一步都在有限时间内完成。
-
反例:一个死循环程序(如
while(true) {...}
)不具备有穷性,因此它不是一个算法。
-
-
确定性
-
含义:算法中的每一步操作都必须有确切、无歧义的定义。对于相同的输入,每次执行都应得到相同的结果。
-
反例:“将x加上一个数”是不确定的,因为“一个数”没有明确定义。必须是“将x加上5”。
-
-
可行性
-
含义:算法中描述的所有操作都是可以通过已经实现的基本运算(如加、减、乘、除、比较、赋值等)执行有限次来实现的。
-
反例:“计算出太阳的质量”在当前技术下对一个程序来说是不可行的,但“计算两个大整数的和”是可行的。
-
-
输入
-
含义:一个算法有零个或多个输入。这些输入是算法开始执行时赋予的初始数据,取自于特定的对象集合。
-
注意:零个输入(即没有输入)也是合法的,例如一个直接输出“Hello, World!”的算法。
-
-
输出
-
含义:一个算法有一个或多个输出。输出是与输入有某种特定关系的量,是算法计算的结果。
-
注意:没有输出的算法是毫无意义的。
-
三、算法设计的时间复杂度计算方法
时间复杂度是衡量算法随问题规模增长,执行时间增长趋势的一个量度。它不计算具体的运行时间(因为那依赖于机器性能),而是计算基本操作执行次数的数量级。
计算方法(核心思想):渐进分析法(大O表示法)
步骤:
-
找出基本操作:找出算法中执行次数最多的、最耗时的那个原操作(如最内层循环中的比较、赋值等)。
-
计算执行次数的函数f(n):分析基本操作的执行次数,将其表示成问题规模
n
的函数f(n)
。 -
取最高阶项,忽略低阶项和常数系数:随着
n
变得非常大,f(n)
的增长速度主要由最高次项决定。使用大O记号O(...)
来表示这个趋势。
大O表示法的规则:
-
用常数1取代运行时间中的所有加法常数。
-
在修改后的运行次数函数中,只保留最高阶项。
-
如果最高阶项存在且其系数不为1,则去除这个系数。