logologo

第十二章:抽象数据类型

Apr 23, 2023

一种限制线性表,其本质上是一个线性表,只是其操作被限定为 LIFO(后进先出)。

一个栈的 ADT 需要暴露的操作有:

  • stack():建栈
  • push():元素入栈
  • pop():栈顶出栈
  • empty():检查栈是否为空

底层实现

  • 对于数组实现,只需要预先开好足够大的数组充当栈,并维护一个整型变量用于存储栈当前大小即可。

  • 对于链表实现,只需要维护一个单链表即可,单链表的表头的下一个元素即为栈顶。

队列

一种限制线性表,相对于栈而言,其限制操作为 FIFO(先进先出)

一个队列的 ADT 需要暴露的操作有:

  • queue():建队列
  • enqueue():元素入队
  • dequeue():队首出队
  • empty():检查队列是否为空

底层实现

  • 对于数组实现,同样是需要开一个足够大的数组,并需要两个变量记录队首和队尾的下标。

考虑到空间利用率可以使用循环队列的实现方法。

对于链表实现,只需要维护一个单链表(表头指向队首)和一个指向队尾的指针即可。

广义线性表

区别于限制线性表,广义线性表不会限制操作。

其存储的数据单元包括 key 和 value 两部分。表严格按 key 升序排序。

这代表其需要实现一个线性表所能做的所有动作:

  • list():建表
  • insert():插入元素
  • delete():删除元素
  • retrieve():查找元素
  • traverse():顺序遍历表
  • empty():检查表是否为空

底层实现

由于其定义十分接近数组和链表,故这两种实现十分简单,不再赘述。

有一个思路是二叉平衡搜索树实现,在保证操作性能的同时也可以使其对外看起来跟一个线性表无异。

这个思路跟鸭子类型类似,但其底层并不是线性的,故其能否称为广义线性表还有待讨论

二叉树

二叉树的定义是其节点只能有 0 ~ 2 个分支。

二叉树一共有四种遍历方式:

  • 前序遍历:先遍历根,再前序遍历左子树,最后前序遍历右子树
  • 中序遍历:先中序遍历左子树,再遍历根,最后中序遍历右子树
  • 后序遍历:先后序遍历左子树,再后序遍历右子树,最后遍历根
  • 层次遍历:BFS 的方式进行遍历,按从上到下从左到右的顺序遍历

二叉搜索树

定义二叉树的每个节点存储一个数(或者其他可以进行大小比较的 ADT),那么当这棵树满足:

左子树的最大节点 < 根 < 右子树的最小节点 左右子树均为二叉搜索树 那么这棵树就是二叉搜索树。

二叉搜索树有一个很重要的性质是其中序遍历的结果是有序的。

如果需要保证其性能则需要进行平衡策略,使其成为二叉平衡搜索树。

将树的概念进行再扩展,不需要强制指定这个数据类型需要有根即为图。

图可以定义为点集+边集。

浙ICP备2021022773号    2022-PRESENT © ZhengKe