数据结构之搜索树(一)

本文介绍了二叉搜索树(BST)的基础概念,包括其性质、搜索、插入和删除操作的时间复杂度,并深入探讨了AVL树作为BST的改进,重点讲解了AVL树的定义、特性、最坏情况的改进以及查找、插入和删除的策略,涉及旋转操作和平衡因子的调整。
摘要由CSDN通过智能技术生成

1. 二叉搜索树(BST):

  • 特征:二叉树key值唯一;左子树key小于根节点的key;右子树的key大于根节点的key;左右子树也为BST。
    中序遍历的结果,是key值按照升序排列的列表,则该树为BST。

  • 抽象数据类型
    搜索,插入,删除的复杂度均为O(logN),

    //二叉树public派生
    //搜索key,从根节点开始,key大根节点右移,key小根节点左移,直到找到key或者根节点变为空。
    template<class Eclass K>
    bool BSTree::Search(const K&k, E&e) const{
    BSTreeNode* p=root;
    while(p){
    if(k>p->data)
    	p=p->rightchild;
    else if(k<p->data)
    	p=p->leftchild;
    else
    	{e=p->data;
    	return true;}
    return false;
    }
    //插入,新插入的节点必定为子叶节点。
    //先搜索,若存在,不插入;否则,插入搜寻最后一个的根节点中。	
    template<class K,class E>
    BSTree<E,K>& BSTree::insert(const E&e){
    BSTreeNode<E>* p=root;
    BSTreeNode<E>* parent=NULL;
    while(p){
    	parent=p;
    if(e>p->data)
    	p=p->rightchild;
    else if(e<p->data)
    	p=p->leftchild;
    else
    	throw BadInput();//找到相同的数。
    }
    BSTreeNode* newnode=new BSTreeNode<E>(e);
    if (root){//是否是空树?
    if(e>pp->data)
    	pp->rightchild=newnode;
    else
    	pp->leftchild=newnode;
    }
    else 
    	root=newnode;
    return *this;
    }
    //删除
    //先看是否存在,存在才进行删除操作。节点为叶节点或者只有一颗子树;否则将节点与直接前驱或者直接后继交换(左子树的最右节点或者右子树的最左节点)转为第一种或者第二种情况,然后进行删除。
    BSTree<E,K>& BSTree::Delete(const K&k,E&e){
    //先搜索节点是否存在
    BSTreeNode<E>* p=root;
    BSTreeNode<E>* parent=NULL;
    while(p&&p->data!=k)
    {	parent=p;
    	if(k<p->data)
    		p=p->leftchild;
    	else
    		p=p->rightchild;
    }
    if(!p)
    	throwbad();
    e=p->data;
    //如果两个子树都存在,寻找左子树的最右节点(直接前驱)做交换。
    if(p->leftchild&&p->rightchild)
    {
    BSTreeNode* s=p->leftchild;
    BSTreeNode* sp=NULL;
    while(s->rightchild)
    	{
    	sp=s;
    	s=s->rightchild;
    	}//找到了直接前驱为s。
    //交换p与其左子树的最右节点。这是怎么交换的?????
    p->data=s->data;
    p=s;
    parent=sp;
    //已经转化为叶节点或者单继承状态
    BSTreeNode<E>* c;
    if(p->leftchild)
    	c=p->leftchild;
    else
    	c=p->rightchild;
    //删除节点p
    if(p==root)
    	root=c;
    else
    {
    if(p==parent->leftchild)
    	pp->leftchild=c;
    else
    	pp->rightchild=c;
    	}
    delete p;
    return *this;
    }
    }
    

2. AVL树:BST的改进

  • 定义:

     T为非空二叉树,TL与TR分别为其左子树与右子树,则当TL,TR满足以下条件时,T为AVL树:
     (1)TL与TR均为AVL树;
     (2)|HL-HR|<=1,即左子树与右子树的高度相差不能超过1。
     因此,空二叉树也为AVL树。
    
  • 特性:

    高度:N节点的AVL树高度为O(logN)
    存在性:对于每一个N值,都存在一棵AVL树,保证了任何时刻的插入操作都是可行的。
    Search复杂度:O(H)=O(logN)
    Insert复杂度:O(logN)
    Delete复杂度:O(logN)
    
  • 最坏情况的改进:

    高度为H的AVL树最少包含的节点数目:Fh=Fh-1+Fh-2+1----->Fh+1=Fh-1+1+Fh-2+1斐波那契数列。
    
  • 描述及查找、插入、删除思路:
    BSTree+平衡因子(balanced factor==H左–H右)
    插入算法:

    插入不平衡:插入节点后只有从根到插入节点路径上的节点平衡因子才会发生改变。设A点为离新插入节点最近的平衡因子为2或-2的节点,则从A到插入节点路径上所有节点原有的bf=0,而A点原有的bf=-1||1。设X点为A类节点中的最后一个。
    (1). 插入新节点后,x未变为A—>插入后仍旧保持平衡:bf(x)=0,插入前后以x为根的子树高度不变,新元素插入了较矮的子树。
    x后代节点bf值为0
    (2). 插入新节点后,x变为A。则A为X点,且新节点插入了较高的子树。
    (3). LL、LR、RL、RR
    旋转:节点从左往右的顺序不变,变的是树枝结构。
    LL的单旋转如下图,RR的单旋转与此对称。
    在这里插入图片描述
    单旋转
    LR的双旋转如下图,RL的双旋转与此对称。//是真没看懂,待补充。
    在这里插入图片描述
    删除算法:
    删除后的不平衡
    R0,R1与LL单旋转类似,R(-1)与LR旋转类似。

    //待补全
    //搜索,与BST搜索方法一致,若k大于节点值,则寻找右子树,否则寻找左子树,直到找到或者子树为空。
    void Search(const K&k,const E&e);
    //插入
    //按照BST的方法查找插入的节点,若存在则不进行插入。同时记录下最近的bf=1或者-1的节点。
    //若不存在这样的节点A,那么插入后不会产生不平衡,从根节点到插入点之间更新bf即可。
    //若存在节点A且bf(A)=-1,插入A的左子树或者bf(A)=1插入A的右子树,那么A的平衡因子变为0,树仍旧平衡,更改A到插入点之间的bf即可。
    //不平衡则根据相应旋转修改bf。
    AVLTree&  AVLTree::Insert(const E&e);
    //删除
    //先删除节点,从被删除节点到根节点路径上的每个节点q都进行判断,修正调整
    AVLTree& AVLTree::Delete(const  E&e)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值