数据结构基础 (代码效率优化, 线性表, 栈, 队列, 数组,字符串,树和二叉树,哈希表)

与代码的结构设计有着紧密关系

一个顺序结构的代码,时间复杂度是O(1), 即任务与算例个数 n 无关

空间复杂度 -- 廉价

数据结构设计有关

数据结构 -- 考虑如何去组织计算机中一定量的数据。 数据结构连接时空,用空间换取时间。 数据处理 -- 了解问题,明确数据操作方法,设计出更加高效的数据结构类型

找到需要处理的数据,计算结果,再把结果保存下来

把结果存到新的内存空间中

把结果存到已使用的内存空间中    

基本操作只有三个:增,删,查

增和删可以细分为数据结构的中间以及最后的增和删

查找可以细分为按照位置条件查找和数据数值特征查找

所有数据处理都是这些基本操着的组合和叠加

只有字典类型数据结构能在 O(1) 的时间复杂度内完成查找动作

回归问题本源,明确数据被处理的动作,来解决数据结构的问题

 

 

 

线性表 n 个具有相同特性的元素的有限序列,Linear List 数据元素之间的关系是一对一的关系

即除了头尾元素外,其它数据元素都是首尾相接的

这句话只适用大部分线性表,而不是全部

比如,循环链表尾的指针指向首位结点

实现方式

最常用的是链式表达,也叫线性链表或链表

每个结点包括具体的数据值和指向下一个结点的指针

单向链表,循环链表,双向链表,双向循环链表

新增和删除为 O(1) 时间复杂度,而查找为 O(n)

适合数据元素个数不确定,且经常进行新增和删除

链表的翻转,快慢指针的方法,是必须掌握的内容

使用数组实现,也叫顺序存储,顺序表

类别

一般线性表,可以自由的删除和添加结点

受限线性表,主要包含栈和队列

栈和队列是特殊的线性表,本质上他们都可以被看作是一类基本结构 线性表案例

链表的翻转

快慢指针

查找奇数个数的链表的中间位置结点的数值

判断链表是否有环

 

 

后进先出的(限制后的)线性表,Last In First Out, Stack. 新增和删除操作只能在这个线性表的表尾进行,即在线性表基础上加了限制

新增: 压栈 push, which adds an element to the collection

删除: 出栈 pop, which removes the most recently added element    

功能上,数组或者链表可以代替栈,但它们灵活性过高,数据量大时有风险 栈顶和栈底是用来表示这个栈的两个指针

栈顶 (top) 是表尾,用来输入数据

栈底 (bottom) 是表头,用来锁定栈内的某一单元的地址

栈有顺序表示和链式表示,分别称作顺序栈和链栈

顺序栈

数组的首元素存在栈底,尾元素放在栈顶

定义指针 top 来指示栈顶元素在数组的位置

可以借助数组来实现

栈中只有一个元素,则 top = 0

以 top 是否为 -1 来判定是否为空栈

栈顶 top 需小于栈的最大容量

出栈操作,只需要 top - 1 即可

链式栈

通常把栈顶放在单链表的头部

top 指针替换了链表原来的尾指针,去掉了头指针

用链表的方式实现

出栈操作,将 top 指针指向栈顶元素的 next 指针即可

对比栈和一般线性表

操作原理相似

时间复杂度一样

都依赖当前位置指针进行数据对象的操作

相同点:

区别:栈只能新增和删除栈顶的数据结点

栈的案例

判断括号字符串是否合法

浏览器页面访问的后退和前进

 

 

队列 先进先出 (限制后的) 线性表, First In First Out, Queue 新增和删除操作只能分别在队尾和队头进行

先进 - 队列的数据新增操作只能在末端进行, add

不允许在队列的中间某个结点后新增数据

先出 - 队列的数据删除操作只能在始端进行, remove

不允许在队列的中间某个结点后删除数据

队列适合面对数据处理顺序非常敏感的问题

可以确定队列长度最大值, 建议使用循环队列

无法确定队列长度时, 应考虑使用链式队列

front 和 rear 两个指针

队头 (front), 用来删除数据

队尾 (rear), 用来增加数据

队列有两种存储方式, 即顺序队列和链式队列

顺序队列

必须有一个固定的长度

实现删除的时间复杂度为 O(1)

使用 flag 来判断队列空或满

每次删除都需要把整个数组前移

时间复杂度为 O(n)

尾指针会向后移动

时间复杂度为 O(1)

数据在内存中也是顺序存储

依赖数组来实现

进行新增插入操作时,

如果只删除头的第一个元素时

使用循环队列

链式队列

让 front 指针指向头结点

头结点不存储数据, 只是辅助标识

数据依赖每个结点的指针互联

是离散存储线性结构

实际上就是尾进头出的单链线性表

在空间上更为灵活

依赖链表来实现

通常会增加一个头结点

当进行数据删除时, 实际删除的是头结点的后继结点

队列为空时, 头尾指针都指向头结点

对比队列和一般线性表

队列继承了线性表的优点和不足

是加了限制的线性表

队列案例

约瑟夫环 - Josephus problem

 

 

数组 数组可以看成是线性表的一种推广,它属于另外一种基本的数据结构 数组是数据结构中的最基本结构

几乎所有的程序设计语言都把数组类型设定为固定的基础变量类型。

可以把数组理解为一种容器,它可以用来存放若干个相同类型的数据元素。

例如:

存放的数据是整数型的数组,称作整型数组;

存放的数据是字符型的数组,则称作字符数组;

另外还有一类数组比较特殊,它是数组的数组,也可以叫作二维数组。

可以把普通的数组看成是一个向量,那么二维数组就是一个矩阵。

数组在内存中是连续存放的,数组内的数据,可以通过索引值直接取出得到。

数组的索引就是对应数组空间

在进行新增、删除、查询操作的时候,完全可以根据代表数组空间位置的索引值进行。

只要记录该数组头部的第一个数据位置,然后累加空间位置即可。

数组的基本操作

具有增删困难、查找容易的特点,可以在任意位置增删数据,所以数组的增删操作会更为多样。

新增操作

若插入数据在最后,则时间复杂度为 O(1)

如果中间某处插入数据,则时间复杂度为 O(n)

删除操作

在数组的最后删除一个数据元素,则时间复杂度是 O(1)

在这个数组的中间某个位置删除一条数据, 时间复杂度为 O(n)

查找操作

如果只需根据索引值进行一次查找,时间复杂度是 O(1)

要在数组中查找一个数值满足指定条件的数据,则时间复杂度是 O(n)。

对比数组和链表

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssxwy.html