- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
王郁昕
算法分析
• 算法每递归查找一次就下降一层 • 所以前面的算法的递归步骤都不超过BST的 树高 • 算法的运行时间都为(h),h为BST的树高
王郁昕
输出BST的排序序列
• 使用中序遍历,可以输出BST树的整个排序 序列
• 在排序序列中有“前驱”和“后继”的概 念
INORDER-TREE-WALK(x) 1 if x ≠ NIL 2 INORDER-TREE-WALK(x.left) 3 访问 x.key 4 INORDER-TREE-WALK(x.right)
王郁昕
AVL-BALANCE(z) #z是新加入的结点 1 y=x=z.p 2 while x ≠ NIL 3 if Height(x.left) - Height(x.right) > 1 #左高右低 4 if Height(x.left.right)<Height( x.left.left) #x.left的左孩子高于右孩子,case1 5 y=x.left 6 RIGHT-ROTATE(T, x) 7 x.h=MaxHeight(x.left, x.right)+1 8 else y=x.left.right # x.left的左孩子低于右孩子,case2 9 LEFT-ROTATE(T, x.left) 10 RIGHT-ROTATE(T, y.p) 11 y.left.h=MaxHeight(y.left.left, y.left.right)+1 12 y.right.h=MaxHeight(y.right.left, y.right.right)+1 13 if Height(x.right) - Height(x.left) > 1 #右高左低 14 if Height(x.right.left)< Height(x.right.right ) #x.right的右孩子高于左孩子,case3 15 y=x.right 16 LEFT-ROTATE(T, x) 17 x.h=MaxHeight(x.left, x.right)+1 18 else y=x.right.left #x.right的的右孩子低于左孩子,case4 19 RIGHT-ROTATE(T, x.right) 20 LEFT-ROTATE(T, y.p) 21 y.left.h=MaxHeight(y.left.left, y.left.right)+1 22 y.right.h=MaxHeight(y.right.left, y.right.right)+1 23 y.h=MaxHeight(y.left, y.right)+1 24 y=x=y.p #平衡检测点向上移动一层,直到2行条件不满足 25 return y #y是树根
处理次序:β,y,x.p, x 注意:旋转后BST的性质不变
王郁昕
LEFT-ROTATE(T, x) #T表示一颗树 1 y = x.right #y指向x的右孩子 2 x.right = y.left #β(y.left)连接上x,孩子指针处理 3 if y.left ≠NIL 4 y.left.p = x #β(y.left)连接上x,父亲指针处理 5 y.p = x.p 6 if x.p == NIL 7 T.root = y 8 else if x == x.p.left #如果x是左孩子 9 x.p.left = y 10 else x.p.right = y 11 y.left = x 12 x.p = y x →11 y →18 11.right →14 14.p →11 18.p →7 7.right →18 18.left →11 11.p →18
#1行 #2行 #4行 #5行 #10行 #11行 #12行
右旋
• 右旋与左旋对称,只需如下对调即可实现 • x与y对调 • left与right对调
王郁昕
AVL树
定义 旋转 插入与删除
王郁昕
AVL树(平衡树)
AVL树是二叉查找树(BST)的一种,并具有以下特性:
• AVL树是一种高度平衡的二叉查找树,对于 每一个结点,其左右子树的高度至多差1 • AVL树的每个结点包括5个数据项: h、key、left、right、p • h表示结点的高度,显然 h(x)=Max(x.left.h, x.right.h)+1 h(leaf)=1
#1行 #2行 #4行 #5行 #10行 #11行 #12行
王郁昕
处理次序: β(2~4) y, x.p(5~10) x(11~12)
β == 14 x →11 y →18
11.right →14 14.p →11 18.p →7 7.right →18 18.left →11 11.p →18
王郁昕
王郁昕
TREE-INSERT(T, z) 1 y = NIL 2 x = T.root 3 while x ≠ NIL 4 y=x #y是x的父亲 5 if z.key < x.key 6 x = x.left 7 else x = x.right 8 z.p = y 9 if y == NIL 10 T.root= z # Tree T was empty 11 else if z.key < y.key 12 y.left = z 13 else y.right = z
y是x的父亲 x==y.left 表明x是y右孩子,即xy
王郁昕
求15的前驱
王郁昕
求6,7,2前驱
6元素满足:1行条件 7元素满足:4行条件 2元素满足:4行条件
求后继首先要回答两个问题: •该元素有左孩子吗?(1行条件) •该元素自己是其父的左孩子吗?(4行条件) 第二个问题一直要问下去,直到条件不满足
3~7确定插入的位置, 11~13插入
王郁昕
构建BST树
根据一个插入序列 反复应用TREE-INSERT
Q =[15,6,18,3,7,17,20,2,4,13,19,9] T .root=Node(DEQUEUE(Q)) while Q ≠ NIL z = Node(DEQUEUE(Q)) TREE-INSERT(T, z)
王郁昕
AVL树的性质定理
• 具有n个结点的AVL树,其高度h=O(log2n) • 一颗高度为h的AVL树至少有Fh个结点,其中 Fh是第h个Fibonacci (斐波那契)数
1, 1, 2, 3, 5, 8, 13, 21,34,...
1/
= 1, 2/1 = 2, 3/2 = 1· 5, 5/3 = 1· 666..., 8/ = 1· 6, 13/8 = 1· 625, 21/13 = 1· 61538... 5
注意定义不是:x.left.key ≤ x.key ≤ x.right.key
王郁昕
查询二叉查找树
TREE-SEARCH (x, k) #递归查询方法 1 if x== NIL or k == x.key 2 return x 3 if k < x.key 4 return TREE-SEARCH(x.left, k) 5 else return TREE-SEARCH(x.right, k)
1
Leonardo Pisano Bigollo (c. 1170 – c. 1250)
王郁昕
AVL树的旋转
• • • • RR旋转(左旋) LL旋转(右旋) RL旋转 LR旋转
• 旋转目的:保持AVL树的性质
王郁昕
王郁昕
王郁昕
王郁昕
AVL树的结点插入
插入操作分两部分: • TREE-INSERT(T, z) #插入结点z • AVL-BALANCE(z) #平衡由于新插入的结点 z而产生的不平衡
求前驱( predecessor )
TREE-PREDECESSOR(x) 1 if x.left ≠ NIL 2 return TREE-MAXIMUM (x.left) 3 y = x.p 4 while y ≠ NIL and x == y.left 5 x=y 6 y = y.p 7 return y
王郁昕
二叉查找树的问题
• 树可能变高,并且可能退化成链,特别是Q 为有序序列时
没有右孩子
没有左孩子
王郁昕
随机构造BST
• 随机排列数组 • 随机构造BST的分析“算法导论”p158
王郁昕
随机排列数组
运行时间为O(n), RANDOM (i, n) 在 i到n之间产生一个随机 数,运行时间为O(1) 利用上述方法可以将待插入BST树的队列元素打乱
王郁昕
Python中的random
import random random.randint(i, n) #random(i, n)
random. shuffle(A)
王郁昕
直接删除结点z
删除的三种情况: • z没有子女,即z是叶子 • z只有一个子女 • z有两个子女(如果二叉查找树中的某个结点有两个子女,则其后 继没有左子女)
ITERATIVE-TREE-SEARCH(x, k) #非递归查询 1 while x ≠ NIL and k ≠ x.key 2 if k < x.key 3 x = x.left 4 else x = x.right 5 return x
王郁昕
求最大和最小关键字元素
TREE-MINIMUM (x) 1 while x.left ≠ NIL 2 x = x.left 3 return x TREE-MAXIMUM(x) 1 while x.right ≠ NIL 2 x = x.right 3 return x
王郁昕
算法分析
• TREE-SUCCESSOR和TREE-PREDECESSOR都是 沿着BST树的路径向上/向下查找,当到达根 /叶子结点时必然能够得到查找的结果,所 以循环处理的次数不会超过树高h • 两算法的运行时间为(h)
王郁昕
二叉查找树的性质
• 如果二叉查找树中的某个结点有两个子女 ,则其后继没有左子女,其前驱没有右子 女
王郁昕
调平衡算法的特点
• 当某一结点出现1<|hL – hR |<3时才调整 • 从z结点采用自底向上的方法调整,直到根 结点。 • 如果z是叶子,则在自底向上的调整路径上 所涉结点的高度无需事先知道,因为它们 会被重新计算(算法第23行)
王郁昕
求结点的高度
#x是一结点 Height(x) 1 h=0 2 if x ≠ NIL 3 h=x.h 4 return h #left,right分别表示左右孩子结点 MaxHeight(left, right) 1 hL=Height(left) 2 hR=Height(right) 3 if hL > hR 4 return hL 5 else return hR
x==y.right 表明x是y右孩子,即xy
王郁昕
求13的后继
王郁昕
求3,4,20的后继
求后继首先要回答两个问题: •该元素有右孩子吗?(1行条件) •该元素自己是其父的右孩子吗?(4行条件) 第二个问题一直要问下去,直到条件不满足
王郁昕
3元素满足:1行条件 4元素满足:4行条件 20元素满足:4行条件
王郁昕
排序序列: 2、3、4、6、7、9、13、15、17、18、20 7的前驱6,后继9 15的前驱13,后继17
王郁昕
求后继( successor )
TREE-SUCCESSOR(x) 1 if x.right ≠ NIL 2 return TREE-MINIMUM (x.right) 3 y = x.p 4 while y ≠ NIL and x == y.right 5 x=y 6 y = y.p 7 return y
目录
• • • • • • • • 第一章 基本概念 第二章 线性表 第三章 栈和队列 第四章 树和二叉树 第五章查找 第六章查找树 第七章 排序 第八章 图
王郁昕
第五章 查找树(BST)
二叉查找树 AVL树 B树
王郁昕
二叉查找树/二叉排序树(BST)
a
b
二叉查找树任何一个结点x包含key、left、right、p 如果y是x左子树的一个结点,则y.key ≤ x.key 如果y是x右子树的一个结点,则x.key ≤ y.key
王郁昕
Baidu Nhomakorabea
AVL树(平衡树)第二种表示
AVL树是二叉查找树(BST)的一种,并具有以下特性:
• AVL树是一种高度平衡的二叉查找树,对于 每一个结点,其左右子树的高度至多差1 • AVL树的每个结点包括5个数据项: bf、key、left、right、p (bf:balance factor平衡因子,结点左子树的 高度减去右子树的高度,即bf=hL-hR) • AVL树中每个结点的bf=-1/0/1
王郁昕
二叉查找树的问题
• 树可能变高,并且可能退化成链
没有右孩子
没有左孩子
王郁昕
结点的旋转
左旋 右旋
王郁昕
结点旋转的目的
• 平衡左右子树的的高度,以便降低整个二 叉查找树的高度,防止树退化成链
• 同时保持二叉查找树的性质不能改变,即 旋转的结果仍然是一颗二叉查找树
王郁昕
结点的旋转
• 左旋:根向左下右上 • 右旋:根向右下左上
王郁昕
删除用到的子程序
目的:都是用v替换u,替换后u仍然表示被替换子树的根。子树并未被删除
王郁昕
删除在前面的3种情况的基础上,又进一步分成4种情况: a, b, c, d
王郁昕
王郁昕
王郁昕
如何删除18
王郁昕
插入、删除的算法分析
• 如果BST的树高为h • TREE-INSERT的运行时间主要是查找插入点 的时间,所以其运行时间为(h) • TREE-DELETE的运行时间除了删除结点外, 还增加了寻找后继的时间,其运行时间为 (h)。于是可得:TREE-DELETE的运行时间 为(h)
• 如果二叉查找树中的某个结点没有右孩子 ,则该结点的后继一定是有左孩子的祖先 ,并且后继的左孩子也同样是该结点的祖 先。(即祖先是右..右左的情况,这里的右左指的是“是右孩子”
或“是左孩子” )
王郁昕
自己总结
• 总结前驱左..左右的情况
左 右 右 右 左
王郁昕
插入结点
• 将新结点z插入到二叉查找树T中,并成为树 的叶子 • z.key==k; z.left==NIL; z.right==NIL • TREE-INSERT(T, z)