数据结构 树(下)

数据结构 树(下)

一、概述

  AVL树、伸展树、红黑树搜索树算法保证最坏情况或者一系列操作情况下,搜索、插入和删除的操作的时间复杂度是O(logn)。本文主要内容包含:平衡搜索树中的AVL树、伸展树、(2,4)树、红黑树 和(a,b)树、B树等实际运用的树数据结构。

二叉搜索树的删除

二、AVL树

1、基本知识

1、AVL树是维持对数O(logn)的高度的特殊二叉搜索树。“高度”指根节点到叶子节点最长路径上的节点的数量。“None”的孩子的高度是0,叶子节点的高度是1,父节点是叶子节点的高度加1

2、AVL树具有 高度平衡属性:对于树T的每个位置P,P的孩子的高度最多相差 1。AVL树子树也是一颗AVL树!

3、一个高度为h(h≥3)的拥有最少节点的AVL树,必须有两颗子树:一颗高度 h-1,另一颗高度为 h-2:n(h)=1+n(h-1)+n(h-2) h≥3 (n(1)=1、n(2)=2)

4、AVL树的高度h和节点总数n的关系:h < 2log n +2

5、AVL树平衡因子是指位置p的两颗子树高度差(左树减右树/右树减左树),平衡因子的绝对值不大于1。

2、更新操作

1、插入,AVL树在叶子节点产生一个新的节点插入新节点p,导致p的祖先节点不满足高度平衡属性,通过trinode重组,两次“旋转”重建树T,使其满足AVL树的高度平衡属性

2、删除,AVL树删除操作导致一个节点拥有或一个孩子,导致树不满足AVL树的高度平衡属性,

3、更新后不满足高度平衡属性的树通过“旋转”:不满足高度平衡属性的节点p需要“旋转”。如果p的孩子节点和子孙节点(非叶子节点的子孙节点)都是左孩子或右孩子,单次旋转,否则trinode重组,从而满足高度平衡属性。如果左、右子孙节点都不是叶子节点,平衡操作是不唯一的!可以单次旋转,也可以 trinode 重组。如果单次旋转和trinode重组都能满足操作,优先进行单次旋转!注:有些子树是维持不变的(static),可以快速确定平衡树结构!

3、AVL树性能

1、标准的二叉搜索树的操作运行时间O(h),AVL树是维持对数O(logn)的高度的特殊二叉搜索树,但是AVL树维护平衡因子和重组一颗AVL树的额外工作受树中路径长度的限制。

2、AVL树运行时间

4、AVL树Python实现

三、伸展树

1、基本知识

1、伸展树在树的高度上没有一个严格的对数上限。伸展树无须额外的高度、平衡或与此树节点关联的其他辅助数据。

2、伸展树的效率取决于某一位置移动到根节点的操作(伸展),每次在插入、删除甚至搜索都是从最底层的位置p开始。

3、伸展操作会使得被频繁访问的元素更快接近于根,从而减少典型的搜索时间。伸展树保障了混合插入、删除、搜素一系列操作的平均操作时间是对数运行的时间

2、伸展(重复操作伸展,知道节点x变成伸展树的根节点)

2.1、zig-zig型 z>y>x-----x>y>z    # y和x都在树的左边或者右边,祖先>父节点>子孙节点;父节点>左孩子+右孩子,位置x深度减少2层

2.2、zig-zag型 z>y>x----x>y+z    # y和x在树的位置相反,祖先>父节点>子孙节点;父节点>左孩子+右孩子,位置x深度减少2层

2.3、zig型 y>x------------x>y        # 父节点>孩子节点,位置x深度减少1层

3、伸展规则

3.1、当搜索键k时,如果在位置P出找到k,则伸展p。否则,在搜素失败的位置伸展叶子节点。存在叶子节点p的key是14并且p的父节点的key是16,没有节点的key是15,搜索14和搜索15都是伸展叶子节点p!

3.2、当插入键k时,伸展新插入的内部节点k

3.3、当删除键k时,在位置p进行伸展,其中p是被移除节点的父节点。del M[k]的两种情况:被移除节点有两种情况:一、移除节点是原来包含键k的节点;二、移除的节点是一个有替代键的后代节点(两个孩子,删除包含键k的节点原来的元素之后,又使用r=befor(p)元素代替p,p节点没有被删除只是替换节点,r节点才被删除,r节点的父节点才是p)。

3.4、位置p和父节点、祖父节点的关系按照zig-zig型、zig-zag型、zig型进行一次或多次伸展操作,直到位置p变为伸展树的根节点

4、伸展摊销分析

4.1、一个简单的zig-zig型、zig-zag型、zig型伸展影响常数数量级的节点,操作时间是O(1)。将位置p进行伸展需要多个伸展组合,如果位置p的深度是d,则将位置p伸展至根节点需要时间是O(d),也就是从位置p的伸展所消耗的时间等同于从根节点到位置p自上而下的搜索!

4.2、最坏的情况:一颗高度为h的伸展树,进行搜索、插入、删除的全部运行时间是O(h),h最大可能接近 n!

4.3、最坏的情况下,伸展树不是一个好的数据结构,但是一系列混合搜索、插入、删除操作中,平均每个操作所需要的时间仅仅是对数时间,在平摊的意义上,伸展树的性能良好!

四、(2,4)树(2-4或2-3-4)

1、基本知识

1、链式存储结构表示一般树(通用树),每个节点配置一个容器,该容器存储指向每个孩子的引用。二级映射:节点的children字段使用列表,表项是指向该节点孩子的引用。

2、使用通用树表示多路搜索树时,必须在每个节点存储一个或多个与该节点相关联的键值对。

3、多路搜索树:树T中每个内部节点w(d-node)至少有两个孩子(d≥2);树T中的每个d-node w,其孩子c1、c2、c3...cd 按顺序存储 d-1 个键值对(k1,v1)、(k2,v2)..........(kd-1,vd-1);定义:k0=- ∞、kd=+∞,每个条目(k,v)存储在一个以 Ci 为根的 w 的子树的一个节点上,其中 i=1,...,d,ki-1≤ k ≤ ki- ∞≤ k ≤ +∞。

4、d-node w存有 d-1 个常规键,如果认为 d-node w 中键集合包含k0=- ∞、kd=+∞,那么存储在一个以 Ci 为根的 w 的子树上的键 k 一定是存储在w上的两个键(k0=- ∞、kd=+∞)“之间” 的一个。

5、一个有n个节点的多路搜索树有n+1个外部节点,多路搜索的外部节点不存储任何数据,仅仅作为占位符,以 None 引用表示!

6、(2,4)树是多路搜索树的一种特殊情况:大小属性:每个内部节点最多有4个孩子(dmax=4);深度属性:所有外部节点具有相同的深度

7、(2,4)树父节点使用一个无序列表或有序数组存储指向孩子节点的引用,因为dmax=4,所有的操作可以达到O(1)

8、由大小属性,深度为h的树的外部节点4h,由深度属性,至少有2h个外部节点。(2,4)树:2h ≤ n+1 ≤ 4h >>> h ≤ log(n+1) ≤ 2h >>>   1/2 log(n+1) ≤ h ≤ log(n+1)

9、分裂操作:(2,4)树节点溢出时,将节点 w 分裂成两个节点 w和 w‘‘。w是 3-node,保存 2个常规键 k1、k2;w‘‘是 2-node,保存 1个常规键 k4;如果 w 是根节点,创建一个新的根节点 U,让 U 称为 w 的父节点,U是一个 2-node,保存 1个常规键 k3;如果 w 不是根节点,分裂后的两个节点 w和 w‘‘替代 w 称为父节点的两个子节点,并且在父节点新增加1个常规键 k3这可能导致溢出传播到 w 的父节点!

10、转移操作:下溢时,节点 w 的兄弟节点 s 是一个 3-node 或者 4-node节点,将 s 的一个键转移到 w 的父节点 u 上,并将 u 的一个键移动到 w 。(根据位置和键的顺序选择合适的 k)

11、融合操作:下溢时,节点 w 的兄弟节点 s 都是 2-node 节点。创建一个新节点 w将 ,w 的父节点 u 上的一个键和兄弟节点 s的一个键融合到w。(根据位置和键的顺序选择合适的 k)

12、(2,4)树新的(k,v)插入是自下向上插入。w 是 4-node时,由于dmax=4 出现溢出情况,才会进行分裂,根据属性调整。否则(k,v)插入在叶子节点。

2、(2,4)树操作:插入、删除

1、插入:新的(k,v)插入到(2,4)树中,如果树 T 中没有键为k的节点,搜索停在外部节点z,令w指向外部节点z的父节点,在w上插入新的(k,v),并且在z的左边对w添加一个新的孩子节点y(外部节点)>>满足深度属性;如果插入前, w 已经是一个 4-node,即 w 存有 3 个常规键。由于dmax=4,增加节点y和新的键值对使得 w 不满足大小属性!即在节点 w 节点溢出。进行分裂操作,调节节点溢出的节点及其父节点的键和孩子节点,可能溢出会一直传播根节点从而创建一个新的根节点!

2、删除:情况一、删除键为k的节点的孩子节点全为None,而且该节点 d≥3,直接删除该节点。情况二、删除键为k的节点的孩子节点全为None,而且该节点 d=2,即该节点的键值对的键只有k,删除k>>不满足深度属性!即在节点 w 下溢。检查 w 的兄弟节点是否有一个 3-node 或者 4-node s,如果有,就进行转移操作;如果没有,进行融合操作融合操作可能一直传播根节点,那根节点被删除!并融合产生新的根节点!

3、(2,4)树性能分析

1、(2,4)树的高度是O(logn)

2、(2,4)树的分裂操作、转移操作、融合操作的操作时间需要O(1)

3、(2,4)树搜索、插入、删除一个节点需要访问O(logn)个节点

五、红黑树

1、基本知识

1、红黑树:一颗带有红色和黑色节点的二叉搜索树,具有属性:

  根属性:根节点是黑色的;

  红色属性:红色节点(如果有)的子节点都是黑色的;>>>>最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节!

  深度属性:具有零个或一个子节点的所有节点都具有相同的黑色深度(被定义为黑色祖先节点(包含父结点,父结点的父结点...)的数量);

  所有的 NULL 叶子节点都是黑色

  所有的 NULL 节点到根节点的路径上的黑色节点数量一定是相同的

2、红黑树:从任一节点到其叶子节点(null)的所有路径都包含相同数目的黑色节点。>>>>所有最长的路径都有相同数目的黑色节点!

3、红黑树通过对从根到叶子节点的路径中各个节点着色方式的限制(红色属性、),从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。

4、给定的一颗红黑树可以构建对应的(2,4)树:合并每一个红色节点 w 到它的父节点,从 w 存储条目到其父节点,并使 w 的子节点变得有序。

5、红黑树的深度属性与(2,4)树的深度属性相对应,每个红黑树的每个黑色节点查号对相应的(2,4)树的每个节点有贡献,所以可以将任意的(2,4)树改编成对应的红黑树。w 有 2-node、3-node、4-node

6、在 2-3-4 树上的插入和删除操作也等同于在红黑树中颜色翻转和旋转

7、红黑树的高度 h:log(n+1)-1 ≤ h ≤ 2 log(n+1)- 2;d=树T深度属性值,令T为树 T 对应的(2,4)树,(2,4)树 T的高度是 h,有红黑树和(2,4)树对应关系得,h=d。由(2,4)树性质得:d ≤  log(n+1)- 1,而且根据红色属性,h ≤ 2d >>> h ≤ 2 log(n+1)- 2;又有二叉树的性质得:log(n+1)-1 ≤ h。最后:log(n+1)-1 ≤ h ≤ 2 log(n+1)- 2

2、红黑树操作:插入、删除

2.1、红黑树插入

1、新插入的节点,如果是根节点,节点为黑色;否则新插入的节点默认为红色

2、红黑树新插入的(k,v),由于红黑树的是二叉树,增加新节点保存(k,v)。

3、新插入的节点(k,v)插入到(2,4)树,插入维持了(2,4)树的深度属性和大小属性,但是可能违反红黑树的红色属性

  新插入的节点 x 的父节点 p 是黑色,直接插入!

  节点 x 处的双红色:新插入的节点 x 的父节点 p 是红色。由节点 p 是红色,所以节点 p 不是根节点;由于原来树 T 满足红色属性,所以节点 p 的父节点 G 是黑色

  3.1、 情况一、节点 p 的兄弟节点 s 是黑色或无:如果节点 x 的父节点 y都在树的左边或右边 单次旋转;如果节点 x 的父节点 y在树的相反边 trinode重组

单次旋转 着色                                                                                                                trinode重组 着色

 

  3.2、情况二、节点 p 的兄弟节点 s 是红色,节点 x 处的双红色表示在相应的(2,4)树 T中溢出。红黑树重新着色相当于(2,4)树 T的分裂操作。红黑树重新着色:将节点 p 和节点 s 着色为黑色,父节点 G 着色为红色(如果父节点 G 是根节点,父节点 G 还是黑色)注:上滤需要一个栈或者保持父链来实现,并且过程复杂!

注:双红问题在重新着色后,双红色会在树 T 更高位置出现,因为 G 可能还有一个红色的父亲节点 Gp。双红问题就从节点 x 传播到节点 G ,在节点 G重新考虑出现双红问题的两种情况!

一、自底向上插入

二、:自顶向下插入

                               

/**
     * 自顶向下插入
     */
    public void insert( AnyType item ){
          nullNode.element=item;
          current=parent=grand=header;
          //自顶向下调整,避免插入的父节点和父节点的兄弟节点为黑色的情况,该情况复杂不利于恢复平衡信心.
          while(compare(item,current)!=0){
              great=grand;
              grand=parent;
              parent=current;
              current=compare(item,current)<0?current.left:current.right;
              if(current.left.color==RED&&current.right.color==RED){
                  handleReorientAfterInsert(item);
              }
          }

          if(current!=nullNode){//重复元素跳过
              return;
          }
          //找到位置
          //构建新的节点
          current=new RedBlackNode<AnyType>(item,nullNode,nullNode);
          //维护与父节点的关系
          if(compare(item,parent)<0){
              parent.left=current;
          }else{
 			  parent.right=current;
          }
          //插入完成后,维护平衡信息
          handleReorientAfterInsert(item);
          nullNode.element=null;
    }
/**
     * 插入后维护平衡信息
     * @param item
     */
    private void handleReorientAfterInsert(AnyType item) {
        //初步调整的变换颜色 自己变为红色,两个儿子变为红色
        current.color=RED;
        current.left.color=BLACK;
        current.right.color=BLACK;
        if(parent.color==RED){
            //调整后破坏了红黑树性质,需要旋转
            //分两种类型 一字形和之字形,之字形比一字形调整了多一步
            grand.color = RED;
            if((compare(item,grand)<0)!=(compare(item,parent)<0)){//之字形
                parent=rotate(item,grand);
                //调整parent和他的儿子,并将调整后的节点W设置成parent
            }
            //调整完成,重新设置当前节点
            current=rotate(item,great);
            //并将当前节点设置为黑色
            current.color=BLACK;
        }
        //保证根节点是黑色
        header.right.color=BLACK;
    }

2.2、红黑树删除

1、红黑树 T 中删除键 K 的项和二叉搜索树的删除过程相似。在结构上,删除至多有一个孩子的节点(或者是最初包含键 K 的节点 p 或者是节点 p 的前继节点),并提升其剩余的子节点

2、红黑树删除节点 p 是红色的==(2,4)树 T表示为 3-node或4-node的转移操作,树的结构没有改变同时满足要求的属性!红黑树删除节点 p 是黑色的==(2,4)树 T表示为 2-node 除去一个项目,树的结构发生改变!在结构上删除至多有一个孩子的节点,并提升其剩余的子节点!

3、删除操作归结于可以删除红色的树叶。一、如果要删除的节点有右儿子,以右儿子的最小元内容替换要删除节点内容,之后删除右儿子最小元来进行删除(最左项)。二、如果只有左儿子,以左儿子最大元内容替换要删除节点的内容,之后删除左儿子最大元(最右项)。三、如果要删除的节点没有儿子, 将该节点调整成红色,将父节点对应的引用设置成nullNode:若父节点为header,将树变为空树;否则如果当前节点为黑色,进行调整,保证删除项为红色,之后将要删除项的父节点的引用设置为nullNode。

4、红黑树删除:情况一、如果删除的节点 p 是红色的,这种结构性变化不会影响树中任何路径的黑色深度,也没有违反红色属性。情况一删除操作在其对应的(2,4)树 T表示为 3-node或4-node的转移操作。情况二、如果删除的非根节点 p 是黑色的:1、节点 p 与兄弟 T 的儿子都是黑色;2、节点 p 的儿子是黑色,兄弟T有一个左儿子是红色;3、节点 p 的儿子是黑色,兄弟T有一个右儿子是红色;4、节点 p 的儿子是黑色,兄弟T儿子都是红色。在相应的(2,4)树 T表示为从一个 2-node 节点中除去一个项目。如果没有重新平衡,删除操作会导致沿着通往删除项的路径的黑色深度不足!

5、如果删除的是左节点,则将前驱的值复制到该节点中,然后删除前驱;如果删除的是右节点,则将后继的值复制到该节点中,然后删除后继。

6、删除前驱或后驱相当于是一种“取巧”的方法,红黑树删除删除节点的目的是使该节点的(k,v)在红黑树上不存在。因此专注于该目的,不关注删除节点时是否真是想删除的那个节点,同时也不需考虑树结构的变化,因为树的结构本身就会因为自动平衡机制而经常进行调整。因为要删除的是左节点 64,找到该节点的前驱 63;然后用前驱的值 63替换待删除节点的值 64,此时两个节点(待删除节点和前驱)的值都为 63!

7、个人理解:前继或后继都是满足至多只有一个孩子的节点。如果是将位置p的(k,v)赋值为前继或后继节点的(k,v)都能维持搜索树的键的结构特性!选择前继和后继节点是一样的而效果!

原文地址:https://www.cnblogs.com/yinminbo/p/11901494.html

时间: 2024-11-10 08:32:24

数据结构 树(下)的相关文章

【数据结构】第6章 树(下)

数据结构第6章 树(下) §6.4 树和森林 6.4.1 树的储存结构 ①父亲表示法(利用每个(除根)结点只有唯一的父亲的性质) ②孩子表示法(用广义表实现) ③孩子兄弟表示法(二叉链表指向第一个孩子结点和下一个兄弟结点) 6.4.2森林与二叉树的转换 二叉树和树都可以用二叉链作为储存结构(分别是孩子表示法和孩子兄弟表示法),给定一棵树,可以找到唯一的一棵二叉树与之对应.两者的物理结构是相同的,只是解释不同而已(旋转). 任何一棵和树对应的二叉树,其右子树必空(因为根是没有兄弟的),在森林中可以

数据结构--树(定义与存储结构)

树基本定义 树的定义 数是具有n个节点的有限集.如图即是一个树形结构. 节点分类 节点的度:一个节点拥有的子节点即成为节点的度,比如A节点,有B和C两个子节点,那么A节点的度=2. 叶节点(终端节点):没有子节点的节点,比如G.H.I.... 如图: 节点间关系 孩子节点:某一个节点的子节点称为孩子节点.比如B.C节点是A节点的孩子节点. 双亲节点:与孩子节点相反.比如,A节点是B.C的双亲节点. 兄弟节点:同一个双亲节点的孩子节点,之间称为兄弟节点.比如,B.C为兄弟节点. 如图: 树的存储结

一步一步写算法(之哈夫曼树 下)

原文:一步一步写算法(之哈夫曼树 下) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面说到了哈夫曼树的创建,那下面一个重要的环节就是哈夫曼树的排序问题.但是由于排序的内容是数据结构,因此形式上说,我们需要采用通用数据排序算法,这在我之前的博客里面已经涉及到了(通用算法设计).所以,我们所要做的就是编写compare和swap两个函数.通用冒泡代码如下所示, void bubble_sort(void* array[], int le

数据结构---树、二叉树、森林

1.基本术语: 度:有两种度"结点的度"与"树的度".结点的度指的是一个结点子树的个数:树的度是指树中结点度的最大值. 叶子结点:指的是没有子树的结点. 层:树是有层次的,一般根结点为第0层.规定根结点到某结点的路径长度为该结点的层数. 深度:树中结点的最大层数 兄弟:同一双亲的结点,互为兄弟 堂兄弟:双亲在同一层次的结点,互为堂兄弟 祖先:从根结点到该结点的路径上的所有结点都是该结点的祖先. 子孙:以某一结点为根的子树上的所有结点都是该结点的子孙 森林:n棵互不相

2017-2018 20172309 《程序设计与数据结构(下)》第七章学习总结

2017-2018 20172309 <程序设计与数据结构(下)>第七章学习总结 一.教材学习内容总结 1.1关于二叉查找树的一些概念 二叉查找树具有附加属性,其左孩子小于父节点.而父节点又小余或者等于右结点. 因此二叉查找树的最右侧会存放最大元素.而其最左侧会存放最小元素. 二叉查找树是二叉树的扩展,它绝大数方法都会用到递归,二叉查找树的平均查找深度为O(log2N). 1.2实现二叉查找树 添加元素(addElement操作) 插入方法首先在插入的时候判断被插入元素的类型是不是Compar

数据结构——树状数组

我们今天来讲一个应用比较广泛的数据结构——树状数组 它可以在O(nlogn)的复杂度下进行单点修改区间查询,下面我会分成三个模块对树状数组进行详细的解说,分别是树状数组基本操作.树状数组区间修改单点查询的实现.树状数组查询最值的实现 一. 树状数组一般分为三种操作,初始化.修改.查询 在讲基本操作之前,我们先来看一张图 这张图就是树状数组的存储方式,对于没有接触过树状数组的人来说看懂上面这张图可能有些困难,上图的A数组就是我们的原数组,C数组则是我们需要维护的数组,这样存储能干什么呢,比如我们在

数据结构 树(上)

数据结构 树(上) 一.概述 主要内容包含树的基本概念.二叉树(平衡二叉树.完全二叉树.满二叉树).搜索树(二叉搜索树.平衡搜索树.AVL树.伸展树.(2,4)树.红黑树).(a,b)树.B树等实际运用的树数据结构 二.基本知识(树的定义和属性) 1.树(非线性数据结构)运用于一些算法实现的效率会比线性数据结构(基于数组的列表和链表)快,广泛运用于文件系统目录结构.图形用户界面.MySQL数据库索引.网站.路由协议和其他计算机系统中 2.树T定义为存储一系列元素的有限节点集合,这些节点具有 pa

数据结构--树的一些计算

先解释一下一些最基本的概念 结点的孩子结点个数即为该结点的度.度为0的结点叫叶子结点.处在树的最顶端(没有双亲)的结点叫根结点. 介绍一下公式 k:总度数k+1:总节点数 为什么总节点数肯定比总度数多1呢?其实很简单可以解释,度可以看作节点与节点之间的线,多1就是显而易见的 设该二叉树总结点数为N,叶子结点个数为n0,度为1的结点个数为n1.度为2的节点个数为n2下面可得两等式:(1) N = n2 + n0 + n1;依据:很显然,二叉树总结点数等于度分别为0,1,2的结点个数总和.(2) N

01-(2)数据结构-树

数据结构——树 标签: 数据结构树 2014-12-07 15:46 972人阅读 评论(0) 收藏 举报  分类: 数据结构(8)  一.树的定义 树是n(n>=0)个结点的有限集.n=0时称为空树,在任意一颗非空树:1.有且仅有一个特定的根结点.2.当n>1时其余结点可分为m(m>0)个互不相交的有限集T1.T2......Tm,其中每一个集合本身又是一棵树,并且称为根的子树. 二.结点的度,拥有的子树称为结点的度 如上图结点A的度是2,结点B的度是1,结点C的度是2,结点E的度是3