收藏 分享(赏)

苏州大学数据结构07.ppt

上传人:dzzj200808 文档编号:3324996 上传时间:2018-10-13 格式:PPT 页数:156 大小:898.50KB
下载 相关 举报
苏州大学数据结构07.ppt_第1页
第1页 / 共156页
苏州大学数据结构07.ppt_第2页
第2页 / 共156页
苏州大学数据结构07.ppt_第3页
第3页 / 共156页
苏州大学数据结构07.ppt_第4页
第4页 / 共156页
苏州大学数据结构07.ppt_第5页
第5页 / 共156页
点击查看更多>>
资源描述

1、1,第七章 搜索结构,数据结构电子教案,殷人昆 王 宏,2,静态搜索表 二叉搜索树 最优二叉搜索树 AVL树 伸展树 红黑树,第七章 搜索结构,3,搜索(Search)的概念,静态搜索表,所谓搜索,就是在数据集合中寻找满足某种条件的数据对象。 搜索的结果通常有两种可能: 搜索成功,即找到满足条件的数据对象。这时,作为结果,可报告该对象在结构中 的位置, 还可给出该对象中的具体信息。 搜索不成功,或搜索失败。作为结果,应报告一些信息, 如失败标志、位置等。,4,通常称用于搜索的数据集合为搜索结构,它是由同一数据类型的对象(或记录)组成。 在每个对象中有若干属性,其中有一个属性,其值可唯一地标识这

2、个对象。称为关键码。使用基于关键码的搜索,搜索结果应是唯一的。但在实际应用时,搜索条件是多方面的,可以使用基于属性的搜索方法,但搜索结果可能不唯一。 实施搜索时有两种不同的环境。 静态环境,搜索结构在插入和删除等操作的前后不发生改变。 静态搜索表,5,动态环境,为保持较高的搜索效率, 搜索结构在执行插入和删除等操作的前后将自动进行调整,结构可能发生变化。 动态搜索表在静态搜索表中,数据元素存放于数组中,利用数组元素的下标作为数据元素的存放地址。搜索算法根据给定值 k,在数组中进行搜索。直到找到 k 在数组中的存放位置或可确定在数组中找不到 k 为止。,静态搜索表,6,数据表与搜索表的类定义,#

3、include #include const int defaultSize = 100; template class dataList; /数据表类的前视定义template class dataNode /数据表中结点类的定义 friend class dataList; /声明其友元类为dataList public:,7,dataNode (const K x) : key(x) /构造函数K getKey() const return key; /读取关键码void setKey (K x) key = x; /修改关键码 private:K key; /关键码域 E other;

4、 /其他域(视问题而定) ; template class dataList /数据表类定义 public:,8,dataList (int sz = defaultSize) : ArraySize(sz), CuurentSize(0) Element = new dataNodesz; assert (Element != NULL);dataList (dataList /求表的长度virtual K getKey (int i) const /提取第 i(1开始)元素值,9,assert (i 0 | i 0 | i /输出,10,friend istreamtemplate boo

5、l dataList:Insert (E& e1) /在dataList的尾部插入新元素, 若插入失败函数返 /回false, 否则返回true.,11,if (CurrentSize = ArraySize) return false;ElementCurrentSize = e1; /插入在尾端CurrentSize+; return true; ;template bool dataList:Remove (K x, E /在表中顺序寻找,12,if (i = CurrentSize) return false; /未找到e1 = Elementi.other; /找到,保存被删元素的值

6、Elementi = ElementCurrentSize-1; /填补CurrentSize-; return true; ;template ostream,数据表类的友元函数,13,for (int i = 1; i istream& operator (istream& in,dataList& InList) ,14,cout InList.CurrentSize; /从in输入表的当前长度cout InList.Elementi-1;return in; ;,15,顺序搜索主要用于在线性表中搜索。 设若表中有 CurrentSize 个元素,则顺序搜索从表的先端开始,顺序用各元素的

7、关键码与给定值 x 进行比较 若找到与其值相等的元素,则搜索成功,给出该元素在表中的位置。 若整个表都已检测完仍未找到关键码与 x 相等的元素,则搜索失败。给出失败信息。,顺序搜索(Sequential Search),16,一般的顺序搜索算法在第二章已经讨论过,本章介绍一种使用“监视哨”的顺序搜索方法。 设在数据表 dataList 中顺序搜索关键码与 给定值 x 相等的数据元素,要求数据元素在表中从下标 0 开始存放, 下标为 CurrentSize 的元素作为控制搜索过程自动结束的“监视哨”使用。 若搜索成功,则函数返回该元素在表中序号 Location(比下标大 1), 若搜索失败,则

8、函数返回 CurrentSize+1。,17,使用监视哨的顺序搜索算法,template int dataList:SeqSearch (const K x) const ElementCurrentSize.key = x;int i = 0; /将x设置为监视哨while (Elementi.key != x) i+; /从前向后顺序搜索return i+1; ;const int Size = 10; main () ,18,dataList L1 (Size); /定义int型搜索表L1int Target; int Loc;cin L1; cout Target; /输入要搜索的数据

9、 if ( (Location = L1.Seqsearch(Target) != L1.Length() ) cout “找到待查元素位置在:” Loc+1 endl; /搜索成功else cout “ 没有找到待查元素n”;/搜索不成功 ;,19,设数据表中有 n 个元素,搜索第 i 个元素的概率为 pi,搜索到第 i 个元素所需比较次数为 ci,则搜索成功的平均搜索长度:在顺序搜索并设置“监视哨”情形:ci = i +1, i = 0, 1, , n-1,因此,顺序搜索的平均搜索长度,20,一般表中各个元素的搜索概率不同,如果按搜索概率的高低排列表中的元素,从有序顺序表的情况可知,能够得

10、到高的平均搜索长度。 在等概率情形,pi = 1/n, i = 1, 2, , n。搜索成功的平均搜索程度为:在搜索不成功情形,ASLunsucc = n+1。,21,采用递归方法搜索值为 x 的元素,每递归一层就向待查元素逼近一个位置,直到到达该元素。假设待查元素在第 i(1in)个位置,则算法递归深度达 i(1i)。,顺序搜索的递归算法,22,顺序搜索的递归算法,template int dataList: SeqSearch (const K x, int loc) const /在数据表 Element1n 中搜索其关键码与给定值 /匹配的对象, 函数返回其表中位置。参数 loc 是在

11、 /表中开始搜索位置if (loc CurrentSize) return 0; /搜索失败else if (Elementloc-1.key = x) return loc;/搜索成功else return Search (x, loc+1); /递归搜索 ;,23,二叉搜索树 ( Binary Search Tree ),定义 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 每个结点都有一个作为搜索依据的关键码(key),所有结点的关键码互不相同。 左子树(如果非空)上所有结点的关键码都小于根结点的关键码。 右子树(如果非空)上所有结点的关键码都大于根结点的关键码。 左子树和右子树

12、也是二叉搜索树。,24,二叉搜索树例,结点左子树上所有关键码小于结点关键码; 右子树上所有关键码大于结点关键码;,注意:若从根结点到某个叶结点有一条路径,路径左边的结点的关键码不一定小于路径上的结点的关键码。,25,如果对一棵二叉搜索树进行中序遍历,可以按从小到大的顺序,将各结点关键码排列起来,所以也称二叉搜索树为二叉排序树。二叉搜索树的类定义#include #include template struct BSTNode /二叉树结点类E data; /数据域BSTNode *left, *right; /左子女和右子女,26,BSTNode() left = NULL; right =

13、NULL; /构造函数BSTNode (const E d, BSTNode *L = NULL, BSTNode *R = NULL) data = d; left = L; right = R;/构造函数BSTNode() /析构函数void setData (E d) data = d; /修改 E getData() return data; /提取bool operator (const E ,27,bool operator (const E /析构函数,28,bool Search (const K x) const /搜索 return Search(x,root) != NU

14、LL; BST,29,bool Remove (const K x) return Remove(x, root); /删除含x的结点 private: BSTNode *root; /根指针K RefValue; /输入停止标志BSTNode * /递归:搜索Search (const K x, BSTNode *ptr);void makeEmpty (BSTNode *,30,BSTNode* Min (BSTNode* ptr); /递归:求最小BSTNode* Max (BSTNode* ptr); /递归:求最大bool Insert (const E二叉搜索树的类定义用二叉链表作

15、为它的存储表示,许多操作的实现与二叉树类似。,31,二叉搜索树的搜索算法,在二叉搜索树上进行搜索,是一个从根结点开始,沿某一个分支逐层向下进行比较判等的过程。它可以是一个递归的过程。 假设想要在二叉搜索树中搜索关键码为 x 的元素,搜索过程从根结点开始。 如果根指针为NULL,则搜索不成功;否则用给定值 x 与根结点的关键码进行比较: 若给定值等于根结点关键码,则搜索成功,返回搜索成功信息并报告搜索到结点地址。,32,若给定值小于根结点的关键码,则继续递归搜索根结点的左子树; 否则。递归搜索根结点的右子树。,搜索45 搜索成功,搜索28 搜索失败,33,template BSTNode* BS

16、T: Search (const K x, BSTNode *ptr) /私有递归函数:在以ptr为根的二叉搜索树中搜 /索含x的结点。若找到,则函数返回该结点的 /地址,否则函数返回NULL值。if (ptr = NULL) return NULL; else if (x data) return Search(x, ptr-left);else if (x ptr-data) return Search(x, ptr-right);else return ptr; /搜索成功 ;,34,template BSTNode* BST: Search (const K x, BSTNode *p

17、tr) /非递归函数:作为对比,在当前以ptr为根的二 /叉搜索树中搜索含x的结点。若找到,则函数返 /回该结点的地址,否则函数返回NULL值。if (ptr = NULL) return NULL; BSTNode* temp = ptr;while (temp != NULL) if (x = temp-data) return temp;if (x data) temp = temp-left;,35,else temp = temp-right;return NULL; ;搜索过程是从根结点开始,沿某条路径自上而下逐层比较判等的过程。 搜索成功,搜索指针将停留在树上某个结点;搜索不成功

18、,搜索指针将走到树上某个结点的空子树。 设树的高度为h,最多比较次数不超过h。,36,二叉搜索树的插入算法,为了向二叉搜索树中插入一个新元素,必须先检查这个元素是否在树中已经存在。 在插入之前,先使用搜索算法在树中检查要插入元素有还是没有。 如果搜索成功,说明树中已经有这个元素,不再插入; 如果搜索不成功,说明树中原来没有关键码等于给定值的结点,把新元素加到搜索操作停止的地方。,37,插入新结点28,二叉搜索树的插入,每次结点的插入,都要从根结点出发搜索插入位置,然后把新结点作为叶结点插入。,38,二叉搜索树的插入算法,template bool BST:Insert (const E,39,

19、else if (e1 data) Insert (e1, ptr-left); /左子树插入else if (e1 ptr-data) Insert (e1, ptr-right); /右子树插入else return false; /x已在树中,不再插入 ;注意参数表中引用型指针参数ptr的使用。 利用二叉搜索树的插入算法,可以很方便地建立二叉搜索树。,40,输入数据 53, 78, 65, 17, 87, 09, 81, 15 ,41,template BST:BST (K value) /输入一个元素序列, 建立一棵二叉搜索树E x; root = NULL; RefValue = v

20、alue; /置空树cin x; /输入数据while ( x.key != RefValue) /RefValue是一个输入结束标志Insert (x, root); cin x; /插入,再输入数据 ;,42,二叉搜索树的删除算法,在二叉搜索树中删除一个结点时,必须将因删除结点而断开的二叉链表重新链接起来,同时确保二叉搜索树的性质不会失去。 为保证在删除后树的搜索性能不至于降低,还需要防止重新链接后树的高度增加。 删除叶结点,只需将其双亲结点指向它的指针清零,再释放它即可。 被删结点右子树为空,可以拿它的左子女结点顶替它的位置,再释放它。,43,被删结点左子树为空,可以拿它的右子女结点顶替

21、它的位置,再释放它。 被删结点左、右子树都不为空,可以在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删结点中,再来处理这个结点的删除问题。,53,78,65,17,87,09,23,45,删除45,右子树空, 用左子女顶替,53,78,65,17,87,09,23,44,88,53,78,88,17,94,09,23,删除78,左子树空, 用右子女顶替,53,94,88,17,09,23,53,78,81,17,94,09,45,删除78,在右子树上找中序下第一个结点填补,23,65,53,81,88,17,94,09,45,23,65,45,二叉搜索树的删除算法,tem

22、plate bool BST:Remove (const K x, BstNode */在右子树中执行删除,46,else if (ptr-left != NULL else /ptr指示关键码为x的结点有一个子女,47,temp = ptr;if (ptr-left = NULL) ptr = ptr-right;else ptr = ptr-left;delete temp;return true;return false; ; 注意在删除算法参数表引用型指针参数的使用。,48,二叉搜索树性能分析,对于有 n 个关键码的集合,其关键码有 n! 种不同排列,可构成不同二叉搜索树有(棵),2,

23、 1, 3 1, 2, 3 1, 3, 2 2, 3, 1 3, 1, 2 3, 2, 1,49,同样 3 个数据 1, 2, 3 ,输入顺序不同,建立起来的二叉搜索树的形态也不同。这直接影响到二叉搜索树的搜索性能。 如果输入序列选得不好,会建立起一棵单支树,使得二叉搜索树的高度达到最大。 用树的搜索效率来评价这些二叉搜索树。 为此,在二叉搜索树中加入外结点,形成判定树。外结点表示失败结点,内结点表示搜索树中已有的数据。 这样的判定树即为扩充的二叉搜索树。,50,举例说明。已知关键码集合 a1, a2, a3 = do, if, to,对应搜索概率p1, p2, p3, 在各搜索不成功间隔内搜

24、索概率分别为q0, q1, q2, q3。可能的二叉搜索树如下所示。,51,判定树,52,在判定树中表示内部结点,包含了关键码集合中的某一个关键码;表示外部结点,代表各关键码间隔中的不在关键码集合中的关键码。 在每两个外部结点间必存在一个内部结点。 一棵判定树上的搜索成功的平均搜索长度ASLsucc可以定义为该树所有内部结点上的搜索概率pi与搜索该结点时所需的关键码比较次数ci (= li, 即结点所在层次) 乘积之和:,53,设各关键码的搜索概率相等:pi = 1/n搜索不成功的平均搜索长度ASLunsucc为树中所有外部结点上搜索概率qj与到达外部结点所需关键码比较次数cj(= lj)乘积

25、之和:设外部结点搜索概率相等:qj = 1/(n+1):,54,设树中所有内、外部结点的搜索概率都相等:pi = 1/3, 1i3, qj = 1/4, 0 j3图(a): ASLsucc = 1/3*3+1/3*2+1/3*1 = 6/3,ASLunsucc = 1/4*3*2+1/4*2+1/4*1 = 9/4。图(b): ASLsucc = 1/3*2*2+1/3*1 = 5/3,ASLunsucc = 1/4*2*4 = 8/4。图(c): ASLsucc = 1/3*1+1/3*2+1/3*3 = 6/3,ASLunsucc = 1/4*1+1/4*2+1/4*3*2 = 9/4。图

26、(d): ASLsucc = 1/3*2+1/3*3+1/3*1 = 6/3,ASLunsucc = 1/4*2+1/4*3*2+1/4*1 = 9/4。,(1) 相等搜索概率的情形,55,图(e): ASLsucc = 1/3*1+1/3*3+1/3*2 = 6/3,ASLunsucc = 1/4*1+1/4*3*2+1/4*2 = 9/4。 图(b)的情形所得的平均搜索长度最小。 一般把平均搜索长度达到最小的扩充的二叉搜索树称作最优二叉搜索树。 在相等搜索概率的情形下,所有内部、外部结点的搜索概率都相等,视它们的权值都为 1。同时,第 k 层有 2k-1个结点,k = 1, 2, 。则有

27、n 个内部结点的扩充二叉搜索树的内部路径长度 I 至少等于序列,56,0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 的前 n 项的和。 因此,最优二叉搜索树的搜索成功的平均搜索长度和搜索不成功的平均搜索长度分别为:,57,设二叉搜索树中所有内、外部结点的搜索概率互不相等。 p1 = 0.5, p2 = 0.1, p3 = 0.05 q0 = 0.15, q1 = 0.1, q2 = 0.05, q3 = 0.05 分别计算各个可能的扩充二叉搜索树的搜索性能,判断哪些扩充二叉搜索树的平均搜索长度最小。,(2) 不相等搜索概率的情形,58,图

28、(a): ASLsucc = 0.5*3+0.1*2+0.05*1 = 1.75,ASLunsucc = 0.15*3+0.1*3+0.05*2+0.05*1 = 0.9。 图(b): ASLsucc = 0.5*2+0.1*1+0.05*2 = 1.2,ASLunsucc = (0.15+0.1+0.05+0.05)*2 = 0.7。,59,图(c): ASLsucc = 0.5*1+0.1*2+0.05*3 = 0.85,ASLunsucc = 0.15*1+0.1*2+0.05*3+0.05*3= 0.75. 图(d) : ASLsucc = 0.5*2+0.1*3+0.05*1 = 1

29、.35,ASLunsucc = 0.15*2+0.1*3+0.05*3+0.05*1 = 0.8.,60,由此可知,图(c)和图(e)的情形下树的平均搜索长度达到最小,因此,图(c)和图(e)的情形是最优二叉搜索树。,图(e) : ASLsucc = 0.5*1+0.1*3+0.05*2 = 0.9;ASLunsucc = 0.15*1+0.1*3+0.05*3+0.05*2 = 0.7;,61,最优二叉搜索树,在相等搜索概率的情形下,因为所有内、外部结点的搜索概率都相等,把它们的权值都视为1。有 n 个内部结点的最优二叉搜索树应为完全二叉树或理想平衡树。 不相等搜索概率情形下的最优二叉搜索树

30、可能不同于完全二叉树的形态。考虑在不相等搜索概率情形下如何构造最优二叉搜索树。 假设关键码集合放在一个有序的顺序表中 key1, key2, key3,keyn ,62,设最优二叉搜索树为T0n,其平均搜索长度为:l i是内部结点 ai 所在层次,lj 是外部结点 j 所在的层次。C0n 是树的代价。为计算方便,将 pi 与 qj 化为整数。 假定:,63,构造最优二叉搜索树,构造最优二叉搜索树采用自底向上的方法。要构造最优二叉搜索树,必须先构造它的左子树和右子树,它们也是最优二叉搜索树。 树的构造从只有一个结点的二叉搜索树开始。 对于任一棵子树 Tij, 它由 keyi+1, keyi+2,

31、 keyj 组成,其内、外部结点的权值分别为 pi+1, pi+2, pj qi, qi+1, qi+2, qj ,64,使用数组Wij来存放它的累计权值和:Wij = qi + pi+1 + qi+1 + pi+2 + qi+2+ pj + qj. 0 i j n 计算Wij可以用递推公式:Wii = qi /不是二叉树, 只有一个外部结点Wii+1 = qi + pi+1 + qi+1 = Wii + pi+1 + qi+1/有一个内部结点及两个外部结点的二叉树Wii+2 = Wii+1 + pi+2 + qi+2/加一个内部结点和一个外部结点的二叉树,65,一般地,Wij = Wij-1

32、 + pj + qj/再加一个内部结点和一个外部结点 对于一棵包括关键码 keyi+1, , keyk-1, keyk, keyk+1, , keyj 的子树Tij, 若设它的根结点为k,i k j,,q0 p1 q1 qi pi+1 qi+1 pi+2 qi+2 ,Wii,Wii+1,Wii+2,66,它的代价Cij为:Cik-1+Wik-1+pk+ Ckj+Wkj Cik-1是其包含关键码 keyi+1, keyi+2, keyk-1 的左子树Tik-1的代价 Cik-1+Wik-1等于把左子树每个结点的路径长度加 1 而计算出的代价 Ckj是包含关键码 keyk+1, keyk+2, k

33、eyj 的右子树Tkj的代价 Ckj+Wkj是把右子树每个结点的路径长度加 1之后计算出的代价。,67,因此,公式Cij = Cik-1 + Wik-1 + pk + Ckj + +Wkj 表明: 整个树的代价等于其左子树的代价加上其右子树的代价,再加上根的权值。 因为 Wij = pk + Wik-1 + Wkj,故有 Cij = Wij + Cik-1 + Ckj 可用 k = i+1, i+2, , j 分别计算上式, 选取使得Cij达到最小的 k。这样可将最优二叉搜索树Tij构造出来。,68,构造的步骤,第一步,构造只有一个内部结点的最优二叉搜索树:T01,T12,Tn-1n。 在Ti

34、-1i (1 i n) 中只包含关键码 keyi。其代价分别是 Ci-1i = Wi-1i。另外设立一 个数组 R0n0n 存放各最优二叉搜索树的根。R01 = 1, R12 = 2, , Rn-1n = n 第二步, 构造有两个内部结点的最优二叉搜索树:T02, T13, , Tn-2n。,69,在Ti-2i中包含两个关键码 keyi-1, keyi。其代价取分别以 keyi-1, keyi 做根时计算出的 Ci-2i 中的小者。 第三步, 第四步, ,构造有 3 个内部结点,有 4 个内部结点, 的最优二叉搜索树。 最后构造出包含有 n 个内部结点的最优二叉搜索树。对于这样的最优二叉搜索树

35、, 若设根为 k, 则根 k 的值存于 R0n 中, 其代价存于 C0n 中, 左子树的根存于 R0k-1 中, 右子树的根存于 Rkn 中。,70,例: 给出关键码集合和内/外部结点的权值序列,第一步,71,第二步,C 115 165 50 60W 90 90 35 35R 1 2 2 3 左子树 T0,0 T0,1 T1,1 T1,2 右子树 T1,2 T2,2 T2,3 T3,3,72,第三步,C 150 190 215W 100 100 100R 1 2 3 左子树 T00 T01 T02 右子树 T13 T23 T33,73,3个关键码 do, if, to 的 最优二叉搜索树,p1

36、=50, p2=10, p3=5,q0=15, q1=10, q2= 5, q3= 5,74,AVL树 高度平衡的二叉搜索树,AVL 树的定义 一棵 AVL 树或者是空树,或者是具有下列性质的二叉搜索树:它的左子树和右子树都是 AVL 树,且左子树和右子树的高度之差的绝对值不超过1。,75,结点的平衡因子 bf (balance factor),每个结点附加一个数字,给出该结点右子树的高度减去左子树的高度所得的高度差,这个数字即为结点的平衡因子bf。 AVL树任一结点平衡因子只能取 -1, 0, 1。 如果一个结点的平衡因子的绝对值大于1,则这棵二叉搜索树就失去了平衡,不再是AVL树。 如果一

37、棵有 n 个结点的二叉搜索树是高度平,76,衡的,其高度可保持在O(log2n),平均搜索长度也可保持在O(log2n)。#include #include “stack.h” template struct AVLNode : public BSTNode /AVL树结点的类定义 int bf;AVLNode() left = NULL; right = NULL; bf = 0; ,AVL树的类定义,77,AVLNode (E d, AVLNode *l = NULL, AVLNode *r = NULL) data = d; left = l; right = r; bf = 0; ;t

38、emplate class AVLTree : public BST /平衡的二叉搜索树(AVL)类定义 public:AVLTree() root = NULL; /构造函数AVLTree (K Ref) RefValue = Ref; root = NULL; /构造函数:构造非空AVL树,78,int Height() const; /高度AVLNode* Search (K x, AVLNode *,79,bool Insert (AVLNode*,80,平衡化旋转,如果在一棵平衡的二叉搜索树中插入一个新结点,造成了不平衡。此时必须调整树的结构,使之平衡化。 平衡化旋转有两类:单旋转

39、(左旋和右旋)双旋转 (左平衡和右平衡) 每插入一个新结点时, AVL 树中相关结点的平衡状态会发生改变。因此, 在插入一 个新结点后,需要从插入位置沿通向根的路径回溯,检查各结点的平衡因子。,81,如果在某一结点发现高度不平衡,停止回溯。从发生不平衡的结点起,沿刚才回溯的路径取直接下两层的结点。 如果这三个结点处于一条直线上,则采用单旋转进行平衡化。单旋转可按其方向分为左单旋转和右单旋转, 其中一个是另一 个的镜像,其方向与不平衡的形状相关。 如果这三个结点处于一条折线上,则采用双旋转进行平衡化。双旋转分为先左后右和先右后左两类。,82,左单旋转 (RotateLeft ),在结点A的右子女

40、的右子树E中插入新结点,该子树高度增1导致结点A的平衡因子变成2,出现不平衡。为使树恢复平衡,从A沿插入路径连续取3个结点A、C和E,以结点C为旋转轴,让结点A反时针旋转。,83,template void AVLTree: RotateL (AVLNode *& ptr) /右子树比左子树高: 做左单旋转后新根在ptr,84,AVLNode *subL = ptr;ptr = subL-right;subL-right = ptr-left;ptr-left = subL; ptr-bf = subL-bf = 0; ;在结点A的左子女的左子树D上插入新结点使其高度增1导致结点A的平衡因子增

41、到-2,造成不平衡。为使树恢复平衡,从A沿插入路径,右单旋转 (RotateRight ),85,h,插入,h,h,h-1,h-1,86,先左后右双旋转 (RotationLeftRight),/左子树比右子树高, 旋转后新根在ptrAVLNode *subR = ptr; /要右旋转的结点ptr = subR-left;subR-left = ptr-right; /转移ptr右边负载ptr-right = subR; /ptr成为新根ptr-bf = subR-bf = 0; ;在结点A的左子女的右子树中插入新结点,该子树高度增1导致结点A的平衡因子变为-2,,87,插入,h,h,A,C,

42、E,D,h-1,h-1,B,F,G,-1,0,0,造成不平衡。 以结点E为旋转轴,将结点B反时针旋转,以E代替原来B的位置。,88,再以结点E为旋转轴,将结点A顺时针旋转。使之平衡化。template void AVLTree:,89,RotateLR (AVLNode *,90,ptr-bf = 0; ;在结点A的右子女的左子树中插入新结点,该子树高度增1。结点A的平衡因子变为2,发生了不平衡。 首先以结点D为旋转轴,将结点C顺时针旋转,以D代替原来C的位置。,先右后左双旋转 (RotationRightLeft),91,再以结点D为旋转轴,将结点A反时针旋转, 恢复树的平衡。,92,A,C

43、,E,D,B,F,G,0,0,-1,template void AVLTree: RotateRL (AVLNode *,93,AVLNode *subR = subL-right;ptr = subR-left;subR-left = ptr-right; ptr-right = subR;if (ptr-bf = 0) subR-bf = 0;else subR-bf = 1;subL-right = ptr-left;ptr-left = subL;if (ptr-bf = 1) subL-bf = -1;else subL-bf = 0;ptr-bf = 0; ;,94,AVL树的插入

44、,在向一棵本来是高度平衡的AVL树中插入一个新结点时,如果树中某个结点的平衡因子的绝对值 |bf| 1,则出现了不平衡,需要做平衡化处理。 AVL树的插入算法从一棵空树开始,通过输入一系列对象关键码,逐步建立AVL树。 在插入新结点后,需从插入结点沿通向根的路径向上回溯,如果发现有不平衡的结点,需从这个结点出发,使用平衡旋转方法进行平衡化处理。,95,设新结点p的平衡因子为0,其父结点为pr。插入新结点后pr的平衡因子值有三种情况: 结点pr的平衡因子为0。说明刚才是在pr的较矮的子树上插入了新结点,此时不需做平衡化处理,返回主程序。子树的高度不变。结点pr的平衡因子的绝对值|bf| = 1。

45、说明插入前pr的平衡因子是0,插入新结点后,以pr为根的子树不需平衡化旋转。但该子树高度,96,增加,还需从结点pr向根方向回溯,继续考查结点pr双亲(pr = Parent(pr)的平衡状态。结点pr的平衡因子的绝对值|bf| = 2。说明新结点在较高的子树上插入,造成了不平衡,需要做平衡化旋转。此时可进一步分2种情况讨论: 若结点pr的bf = 2,说明右子树高,结合其右子女q 的bf分别处理:,97,若q的bf为1,执行左单旋转。若q的bf为-1,执行先右后左双旋转。,左单旋转,插入后,右左双旋转,插入后,98,若结点pr的bf = -2,说明左子树高,结合其左子女q 的bf分别处理:

46、若q的bf为-1,执行右单旋转; 若q的bf为1,执行先左后右双旋转。下面举例说明在AVL树上的插入过程。,右单旋转,左右双旋转,99,例如,输入关键码序列为 16, 3, 7, 11, 9, 26, 18, 14, 15 ,插入和调整过程如下。,左右双旋,右单旋,100,101,15,18,2,3,18,16,-2,左右双旋,7,3,0,0,0,11,7,14,9,-1,16,15,0,1,11,26,26,14,1,-2,9,从空树开始的建树过程,102,AVL树的删除,如果被删结点x最多只有一个子女,可做简单删除: 将结点x从树中删去。 因为结点x最多有一个子女,可以简单地把x的双亲中原来指向x的指针改指到这个子女结点; 如果结点x没有子女,x双亲原来指向x的指针置为NULL。 将原来以结点x为根的子树的高度减1。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报