【第一章】数据结构——预备知识

【第一章】数据结构------预备知识

本章我们就正式进入了数据结构的部分,那么在本章中将会介绍数据结构的来源,还有相关的概念术语,以及对于时空复杂度的详解。


为什么我们需要数据结构

数据结构是计算机科学中组织和存储数据的方式,直接影响程序的效率、可读性和可维护性。合理选择数据结构可以优化资源使用,提升性能。不同的数据结构在操作(如插入、删除、搜索)上有不同的时间复杂度。例如,哈希表可以实现平均O(1)时间复杂度的查找,而数组则需要O(n)。选择合适的数据结构能显著减少计算资源消耗。数据结构的设计影响内存占用,链表适合频繁插入删除的场景,而数组更适合随机访问。压缩数据结构如位图或布隆过滤器可以在特定场景下大幅节省内存。许多复杂问题可以通过适当的数据结构抽象化。图结构能建模网络关系,树结构能表示层次数据,堆能高效处理优先级队列。数据结构提供了一种问题分解和建模的工具。良好设计的数据结构使代码更易理解和维护。封装数据操作接口,隐藏实现细节,可以减少代码耦合度。标准数据结构如栈、队列等提供了通用的设计模式。大多数算法依赖于特定的数据结构。排序算法需要可随机访问的集合,最短路径算法需要图结构。数据结构与算法紧密相关,共同决定了程序的整体性能。数据结构能有效表示现实世界中的关系和模式。数据库索引使用B树,社交网络使用图结构,文件系统使用树状结构。选择合适的数据结构可以更自然地映射实际问题。

当然,数据结构本身可以供我们使用来更好的管理数据,同样的在算法中我们也会大量使用到数据结构。

常用的数据结构

这里我尽量为大家列举,不仅包括我们一般计算机学生上课所接触的,还有一些竞赛中经常使用的数据结构。

  • 线性结构:顺序表,单链表,双向链表,栈和队列(操作受限的线性表),串,数组,广义表,哈希表(散列表)
  • 非线性结构:树(二叉树,二叉搜索树,二叉平衡树,AVL/红黑树,堆(本质是完全二叉树),Trie,B+/B-树),图
  • 特殊的数据结构:并查集(森林),跳表,布隆过滤器,线段树,树状数组

数据结构相关概念术语(易混淆)

下面是一些教材上常见的一些概念术语,可能在开发环境中不会经常使用了,但是应付一般的考试足够了。

  • 数据:数据是信息的载体
  • 数据元素:是数据的基本单位
  • 数据项:是组成数据元素的、拥有独立含义的、不可分割的最小单位
  • 数据对象:是性质相同的数据元素的集合,是数据的一个子集。

数据结构的存储形式

逻辑结构

  • 集合结构
  • 线性结构
  • 树结构
  • 图结构和网状结构

存储结构

  • 顺序存储结构
  • 链式存储结构

抽象数据类型(ADT)

抽象数据类型是一种数学模型,用于描述数据的逻辑结构和操作,而不涉及具体实现细节。它通过封装数据和对数据的操作,隐藏内部实现,仅暴露接口给用户。

ADT的核心特征

数据抽象 将数据的具体表示与使用分离,用户只需知道能执行哪些操作,无需了解数据如何存储或操作如何实现。

封装性 ADT将数据和操作绑定在一起,形成一个独立的模块。外部只能通过定义的接口访问数据,无法直接操作内部数据。

ADT的组成要素

数据对象 描述ADT中数据的逻辑结构,例如栈中的元素遵循后进先出(LIFO)原则。

操作集合 定义对数据对象的所有合法操作。以栈为例,基本操作包括:

  • push(item):将元素压入栈顶
  • pop():移除并返回栈顶元素
  • peek():查看栈顶元素但不移除
  • isEmpty():检查栈是否为空

ADT的实现方式

物理实现 ADT可通过不同数据结构实现。例如栈可以用数组或链表实现:

数组实现:需要预先分配固定大小空间

链表实现:动态分配内存,更灵活

接口与实现分离 在任何编程语言中,ADT都强调接口定义与具体实现的分离。例如C语言中用头文件声明接口,源文件实现具体功能。

ADT的典型示例

队列ADT

数据对象:先进先出(FIFO)的元素序列

操作集合:

enqueue(item):在队尾添加元素

dequeue():移除队首元素

front():获取队首元素

isEmpty():检查队列是否为空

二叉树ADT

数据对象:具有根节点和左右子树的层次结构

操作集合:

insert(key):插入新节点

search(key):查找特定节点

traverse(mode):按指定顺序遍历(前序、中序、后序)

ADT的设计原则

信息隐藏 只暴露必要的操作接口,隐藏数据存储和算法细节。例如栈不暴露当前容量或扩容策略。

一致性保证 操作应维护数据的不变式。例如执行pop操作前必须确保栈非空,否则应抛出异常或返回错误代码。

算法和算法分析

算法是解决特定问题的一系列明确指令,具有以下特性:

有穷性:必须在有限步骤内终止。

确定性:每条指令无歧义。

可行性:可通过基本操作实现。

输入/输出:有零个或多个输入,至少一个输出。

算法效率的衡量标准

时间复杂度描述算法运行时间随输入规模的增长趋势,常用大O符号表示:

时间复杂度

时间复杂度用于衡量算法执行时间随输入规模增长的变化趋势。它不计算实际运行时间,而是分析操作次数的增长级数,通常用大O符号(O)表示。

常见时间复杂度类型

  • O(1) 常数时间

    算法的执行时间不随输入规模变化。例如访问数组元素或哈希表查找。

  • O(log n) 对数时间

    执行时间与输入规模的对数成正比。常见于二分查找或平衡二叉树的搜索操作。

  • O(n) 线性时间

    执行时间与输入规模呈线性关系。例如遍历数组或链表。

  • O(n log n) 线性对数时间

    常见于高效排序算法如快速排序、归并排序。

  • O(n²) 平方时间

    通常出现在嵌套循环中,如冒泡排序或选择排序。

  • O(2ⁿ) 指数时间

    多见于递归解决子问题重叠的情况,如暴力破解算法。

时间复杂度的计算方法

忽略低阶项

对于表达式如 3n² + 2n + 1,仅保留最高阶项 n²,记为 O(n²)。

忽略常数系数

若操作次数为 5n,时间复杂度仍记为 O(n)。

例外:循环结构的分析

单层循环:若循环次数与 n 成正比,记为 O(n)。

嵌套循环:若每层循环次数为 n,则 k 层嵌套为 O(nᵏ)。

递归算法的分析

使用递归树或主定理(Master Theorem)计算。例如斐波那契数列的递归实现为 O(2ⁿ)。

时间复杂度的实际意义

算法选择依据:处理大规模数据时,优先选择 O(n log n) 而非 O(n²) 的算法。

性能优化方向:通过降低时间复杂度优化关键代码段。

资源预估:帮助预估算法在数据增长时的可扩展性。

⚠️注意事项:

最坏与平均情况:某些算法(如快速排序)需区分最坏和平均时间复杂度。

实际因素影响:缓存、硬件差异等可能导致实际表现与理论分析不符。

空间换时间:哈希表等数据结构通过增加空间复杂度来降低时间复杂度。


通常来说。对于时间复杂度的计算,我们经常会按照算法的执行的次数来评估,根据数学知识可以知道,在一个表达式当中影响最大的就是未知数的最高阶数次。那么这就是时间复杂度的计算方式。


好的,那么数据结构部分的前置知识就介绍到这里。本章介绍了数据结构的相关术语,存储形式以及算法的分析。下一章我们开始进行线性表的讲解,这不仅是数据结构最为基础的部分,也是后面更复杂数据结构的基础。那么下一章我们不见不散~

相关推荐
皮肤科大白1 小时前
X-AnyLabeling +9.5 G Medsam3全流程接入笔记
pytorch·笔记·深度学习
小菜鸡桃蛋狗2 小时前
C++——vector
开发语言·c++·算法
wicb91wJ62 小时前
手写一个Promise,彻底掌握异步原理
开发语言·前端·javascript
噜噜噜阿鲁~2 小时前
python学习笔记 | 7.2、高级特性-迭代
笔记·python·学习
大锤资源2 小时前
质性研究“铁三角揭秘“认识论、方法论与方法
经验分享
Engineer邓祥浩2 小时前
知识点1 时间复杂度、空间复杂度
java·数据结构·算法
小小仙。2 小时前
IT自学第三十七天补充
java·开发语言
yuezhilangniao2 小时前
tshark + tcpdump 入门实战笔记:从网站分析到 DDoS 模拟
笔记·ddos·tcpdump
少司府2 小时前
C++基础入门:初识模板
开发语言·c++·c·模板·函数模板·类模板·泛型编程
jinanwuhuaguo2 小时前
OpenClaw范式深度剖析:从技术突破到安全治理的系统性研究(第二篇)
开发语言·人工智能·安全·架构·kotlin·openclaw