算法(四)数据结构 II

1. ADT地图

get(k):如果映射M有一个键为k的条目,返回它的相关值
put(k, v):如果key k不在M中,那么插入(k, v)到映射M中;否则,用v替换与k相关的现有值
remove(k):如果地图M有一个键为k的条目,移除它
entrySet():返回M中条目的可迭代集合
keySet():返回一个可迭代的M中键的集合
values():返回M中值的可迭代集合
size(),isEmpty ()

在这里插入图片描述

2. 二叉搜索树 Binary Search Trees (BST)

二叉搜索树是存储满足以下BST属性的键(或键-值对)的二叉树
对于树中的任意节点v, v左子树中的任意节点u, v右子树中的任意节点w,
key(u) < key(v) < key(w)
注意,二叉搜索树的顺序遍历是按递增顺序访问键的。

用二叉搜索树进行搜索
为了搜索关键字k,我们从根结点开始沿着一条向下的路径
为了决定是向左还是向右,我们将当前节点v的键值与k进行比较
如果我们到达一个外部节点,这意味着键不在数据结构中
在这里插入图片描述
运行时间为O(h),其中h是树的高度
最坏情况是h = n
最好的情况是h = log2n

2.1 插入

为了执行操作put(k, o),我们搜索关键字k(使用search)
如果在树中找到k,用o替换对应的值
如果没有找到k,设w为搜索到的外部节点。我们用一个保持(k, o)的内部节点替换w
例子:insert 23
在这里插入图片描述

2.2 删除

为了执行remove(k)操作,我们搜索键k(使用搜索),以找到持有k的节点w
我们区分两种情况:

  • w有一个外部子结点
  • w有两个内部子结点

w有一个外部子结点
假设我们想要移除的节点w有一个外部子节点,我们称之为z。
为了移走w:

  • 从树中移除w和z
  • 提升w的另一个孩子取代w的位置
    在这里插入图片描述

w有两个内部子结点
假设我们想要移除的节点w有两个内部子节点。
为了移走w:

  • 在有序遍历中找到w后面的内部节点y(即,y在w下的右子树中具有最小的键值)
  • 我们将该项从y复制到节点w中
  • 我们删除节点y和它的左子节点z,它必须是外部的,使用前面的情况
    在这里插入图片描述

2.3 复杂性

考虑一个由高度为h的二叉搜索树实现的有n个项的映射:

  • 使用的空间是O(n)
  • 取、放、移取时间为O(h)

高度h在最坏情况下可以是n,最好情况下是log n。
因此,我们能期望的最好结果是树操作需要O(log n)时间,但通常我们只能保证O(n)。但前者可以通过更好的插入例程来实现。

2.4 保持平衡的BST

我们已经看到运行BSTs的操作需要O(height)时间。不幸的是,标准插入实现可能导致树的高度为n-1(例如,如果我们按照排序的顺序插入)。在今天余下的课程中,我们将讨论更复杂的算法,这些算法通过简单的局部变换来重新平衡树,从而始终保持高度为O(log n)的BST。

改善平衡:Trinode重组
设x, y, z为结点,使x是y的子结点,y也是z的子结点。
设a b c是x y z的顺序列表
执行旋转,使b成为三个节点中最上面的节点。
在这里插入图片描述

3. 秩平衡树 rank-balance tree

3.1 AVL树

定义
AVL树是秩平衡树,其中r(v)是其根为v的子树的高度
平衡约束:每个内部节点的两个子树的秩最多相差1。
存储n个键的AVL树的高度是O(log n)

性质
假设我们有一个存储n个元素的AVL树
-数据结构使用O(n)空间
-树的高度O(log n)
-搜索花费O(log n)时间
-插入花费O(log n)时间
-移除花费O(log n)时间

4. 优先队列ADT

特殊类型的ADT映射存储键值项的集合,其中我们只能删除最小的键:

  • insert(k,v): 插入键k和值v
  • remove_min():删除并返回键值最小的项
  • min():返回具有最小键值的项
  • size():返回存储了多少项
  • is_empty():测试队列是否为空
    在这里插入图片描述

4.1 基于优先级队列

未排序的列表实现

  • insert在O(1)时间,因为我们可以在序列的开始或结束插入项
  • remove_min和min需要O(n)时间,因为我们必须遍历整个列表以找到最小的键

排序的列表实现

  • insert在O(n)时间内,因为我们必须找到插入项的位置
  • remove_min和min在O(1)时间,因为最小的键在开始
    在这里插入图片描述

4.2 优先队列排序

我们可以使用优先队列排序键列表:

  1. 迭代地将键插入空的优先队列
  2. 迭代地remove_min以排序的顺序获取键

复杂性分析:

  • n次插入操作
  • n个remove_min操作
    基于序列的实现采取O(n^2)

4.3 选择排序

pq-sort的变体使用未排序序列实现:

  1. 用n个插入操作插入元素需要O(n)时间
  2. 用n个remove_min操作删除元素需要O(n2)

可以就地完成(不需要额外空间)
顶层循环不变式:

  • A (0, i)是有序的
  • A[i, n]是优先队列

在这里插入图片描述

4.4 插入排序

pq-sort的变体使用排序序列实现:

  1. 通过n次插入操作插入元素需要O(n2)时间
  2. 使用n个remove_min操作删除元素需要O(n)

可以就地完成(不需要额外空间)
顶层循环不变式:

  • A[0, i]是优先队列(因此排序)
  • A[i, n]是剩下的
    在这里插入图片描述

5. 堆数据结构 heap data strycture

堆是一棵在节点上存储(键、值)项的二叉树,满足以下属性:

  1. 堆序:对于每个m≠根节点,Key(m)>=key(parent(m))
  2. 完全二叉树:设h为高度
    • 每一级i < h都满了(即有2i节点)
    • 剩余节点位于h级最左侧位置

根始终持有堆中最小的键
存储n个键的堆高度为log n

5.1 插入到堆中

-用给定的密钥创建一个新节点
-找到新节点的位置
-恢复堆序属性
在这里插入图片描述
Upheap
通过从插入点开始沿向上路径交换键来恢复堆序属性
正确性:交换后以z为根的子树具有该属性
复杂度:O(log n)时间,因为堆的高度是log n
在这里插入图片描述

5.2 从堆中移除

-用最后一个节点w的键替换根键
-删除w
-恢复堆序属性
在这里插入图片描述
downheap
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值