族谱网 头条 人物百科

二叉搜索树

2017-10-16
出处:族谱网
作者:阿族小谱
浏览:641
转发:0
评论:0
二叉搜索树的查找算法在二叉搜索树b中查找x的过程为:若b是空树,则搜索失败,否则:若x等于b的根节点的数据域之值,则查找成功;否则:若x小于b的根节点的数据域之值,则搜索左子树;否则:查找右子树。/*以下代码为C++写成,下同*/StatusSearchBST(BiTreeT,KeyTypekey,BiTreef,BiTree&p){//在根指针T所指二元查找樹中递归地查找其關键字等於key的數據元素,若查找成功,//則指针p指向該數據元素節點,并返回TRUE,否則指针指向查找路徑上訪問的最後//一個節點并返回FALSE,指针f指向T的雙親,其初始调用值為NULLif(!T){//查找不成功p=f;returnfalse;}elseif(key==T->data.key){//查找成功p=T;returntrue;}elseif(keydata.key)//在左子樹中繼續查找returnS...

二叉搜索树的查找算法

在二叉搜索树b中查找x的过程为:

若b是空树,则搜索失败,否则:

若x等于b的根节点的数据域之值,则查找成功;否则:

若x小于b的根节点的数据域之值,则搜索左子树;否则:

查找右子树。

/* 以下代码为C++写成,下同*/StatusSearchBST(BiTreeT,KeyTypekey,BiTreef,BiTree&p){//在根指针T所指二元查找樹中递归地查找其關键字等於key的數據元素,若查找成功,//則指针p指向該數據元素節點,并返回TRUE,否則指针指向查找路徑上訪問的最後//一個節點并返回FALSE,指针f指向T的雙親,其初始调用值為NULLif(!T){//查找不成功p=f;returnfalse;}elseif(key==T->data.key){//查找成功p=T;returntrue;}elseif(keydata.key)//在左子樹中繼續查找returnSearchBST(T->lchild,key,T,p);else//在右子樹中繼續查找returnSearchBST(T->rchild,key,T,p);}

在二叉搜索树插入节点的算法

向一个二叉搜索树b中插入一个节点s的算法,过程为:

若b是空树,则将s所指结点作为根节点插入,否则:

若s->data等于b的根节点的数据域之值,则返回,否则:

若s->data小于b的根节点的数据域之值,则把s所指节点插入到左子树中,否则:

把s所指节点插入到右子树中。(新插入节点总是叶子节点)

/*当二元搜尋樹T中不存在关键字等于e.key的数据元素时,插入e并返回TRUE,否则返回FALSE*/StatusInsertBST(BiTree*T,ElemTypee){if(!T){s=newBiTNode;s->data=e;s->lchild=s->rchild=NULL;T=s;//被插節点*s为新的根结点}elseif(e.key==T->data.key)returnfalse;//关键字等于e.key的数据元素,返回錯誤if(e.keydata.key)InsertBST(T->lchild,e);//將e插入左子樹elseInsertBST(T->rchild,e);//將e插入右子樹returntrue;}

在二叉查找树删除结点的算法

二叉搜索树

  删除一个有左、右子树的节点

在二叉查找树删去一个结点,分三种情况讨论:

若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。

若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉查找树的特性。

若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:其一是令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树,*s为*p左子树的最右下的结点,而*p的右子树为*s的右子树;其二是令*p的直接前驱(in-order predecessor)或直接后继(in-order successor)替代*p,然后再从二叉查找树中删去它的直接前驱(或直接后继)。

在二叉查找树上删除一个结点的算法如下:

StatusDeleteBST(BiTree*T,KeyTypekey){//若二叉查找树T中存在关键字等于key的数据元素时,则删除该数据元素,并返回//TRUE;否则返回FALSEif(!T)returnfalse;//不存在关键字等于key的数据元素else{if(key==T->data.key){// 找到关键字等于key的数据元素returnDelete(T);}elseif(keydata.key)returnDeleteBST(T->lchild,key);elsereturnDeleteBST(T->rchild,key);}}StatusDelete(BiTree*p){//该节点为叶子节点,直接删除BiTree*q,*s;if(!p->rchild&&!p->lchild){deletep;p=NULL;}elseif(!p->rchild){//右子树空则只需重接它的左子树q=p->lchild;p->data=p->lchild->data;p->lchild=p->lchild->lchild;p->rchild=p->lchild->rchild;deleteq;}elseif(!p->lchild){//左子树空只需重接它的右子树q=p->rchild;p->data=p->rchild->data;p->lchild=p->rchild->lchild;p->rchild=p->rchild->rchild;deleteq;}else{//左右子树均不空q=p;s=p->lchild;while(s->rchild){q=s;s=s->rchild;}//转左,然后向右到尽头p->data=s->data;//s指向被删结点的“前驱”if(q!=p)q->rchild=s->lchild;//重接*q的右子树elseq->lchild=s->lchild;//重接*q的左子树deletes;}returntrue;}

在C语言中有些编译器不支持为 struct Node 节点分配空间,声称这是一个不完全的结构,可使用一个指向该 Node 的指针为之分配空间。

如: sizeof( Probe ) , Probe 作为二叉树节点在 typedef 中定义的指针。

Python实现:

deffind_min(self):# Gets minimum node (leftmost leaf) in a subtreecurrent_node=selfwhilecurrent_node.left_child:current_node=current_node.left_childreturncurrent_nodedefreplace_node_in_parent(self,new_value=None):ifself.parent:ifself==self.parent.left_child:self.parent.left_child=new_valueelse:self.parent.right_child=new_valueifnew_value:new_value.parent=self.parentdefbinary_tree_delete(self,key):ifkeyself.key:self.right_child.binary_tree_delete(key)else:# delete the key hereifself.left_childandself.right_child:# if both children are presentsuccessor=self.right_child.find_min()self.key=successor.keysuccessor.binary_tree_delete(successor.key)elifself.left_child:# if the node has only a *left* childself.replace_node_in_parent(self.left_child)elifself.right_child:# if the node has only a *right* childself.replace_node_in_parent(self.right_child)else:# this node has no childrenself.replace_node_in_parent(None)

二叉查找树的遍历

中序遍历(in-order traversal)二叉查找树的Python代码:

deftraverse_binary_tree(node,callback):ifnodeisNone:returntraverse_binary_tree(node.leftChild,callback)callback(node.value)traverse_binary_tree(node.rightChild,callback)

排序(或称构造)一棵二叉查找树

用一组数值建造一棵二叉查找树的同时,也把这组数值进行了排序。其最差时间复杂度为 O ( n 2 ) {\displaystyle O(n^{2})} 。例如,若该组数值经是有序的(从小到大),则建造出来的二叉查找树的所有节点,都没有左子树。自平衡二叉查找树可以克服上述缺点,其时间复杂度为O( n log n )。一方面,树排序的问题使得CPU Cache性能较差,特别是当节点是动态内存分配时。而堆排序的CPU Cache性能较好。另一方面,树排序是最优的增量排序(incremental sorting)算法,保持一个数值序列的有序性。

defbuild_binary_tree(values):tree=Noneforvinvalues:tree=binary_tree_insert(tree,v)returntreedefget_inorder_traversal(root):""" Returns a list containing all the values in the tree, starting at *root*. Traverses the tree in-order(leftChild, root, rightChild). """result=[]traverse_binary_tree(root,lambdaelement:result.append(element))returnresult

二叉查找树性能分析

每个结点的 C i {\displaystyle C_{i}} 为该结点的层次数。最坏情况下,当先后插入的关键字有序时,构成的二叉查找树蜕变为单支树,树的深度为 n {\displaystyle n} ,其平均查找长度为 n + 1 2 {\displaystyle {\frac {n+1}{2}}} (和顺序查找相同),最好的情况是二叉查找树的形态和折半查找的判定树相同,其平均查找长度和 log 2 ⁡ ⁡ --> ( n ) {\displaystyle \log _{2}(n)} 成正比( O ( log 2 ⁡ ⁡ --> ( n ) ) {\displaystyle O(\log _{2}(n))} )。

二叉查找树的优化

请参见主条目平衡树。

Size Balanced Tree(SBT)

加衡树(WBT)

AVL树

红黑树

Treap(Tree+Heap)

这些均可以使查找树的高度为 O ( log ⁡ ⁡ --> ( n ) ) {\displaystyle O(\log(n))}

参见

跳跃列表

 


免责声明:以上内容版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。感谢每一位辛勤著写的作者,感谢每一位的分享。

——— 没有了 ———
编辑:阿族小谱

更多文章

更多精彩文章
评论 {{commentTotal}} 文明上网理性发言,请遵守《新闻评论服务协议》
游客
发表评论
  • {{item.userName}} 举报

    {{item.content}}

    {{item.time}} {{item.replyListShow ? '收起' : '展开'}}评论 {{curReplyId == item.id ? '取消回复' : '回复'}}

    回复评论
加载更多评论
打赏作者
“感谢您的打赏,我会更努力的创作”
— 请选择您要打赏的金额 —
{{item.label}}
{{item.label}}
打赏成功!
“感谢您的打赏,我会更努力的创作”
返回
打赏
私信

推荐阅读

· 二叉树
[图论]中的定义二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根节点的度不大于2。有了根节点之后,每个顶点定义了唯一的父节点,和最多2个子节点。然而,没有足够的信息来区分左节点和右节点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。二叉树(BinaryTree)的类型二叉树是一个有根树,并且每个节点最多有2个子节点。非空的二叉树,若树叶总数为n0,分支度为2的总数为n2,则n0=n2+1。一棵深度为k,且有2k−−-->1{\displaystyle2^{\begin{aligned}k\end{aligned}}-1}个节点的二叉树,称为满二叉树(FullBinaryTree)。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉...
· 蒙特卡洛树搜索
历史基于随机抽样的蒙特卡洛方法可以追溯到20世纪40年代。布鲁斯·艾布拉姆森(BruceAbramson)在他1987年的博士论文中探索了这一想法,称它“展示出了准确、精密、易估、有效可计算以及域独立的特性“。他深入试验了井字棋,然后试验了黑白棋和国际象棋的机器生成的评估函数。1992年,B·布鲁格曼(B.Brügmann)首次将其应用于对弈程序,但他的想法未获得重视。2006年堪称围棋领域蒙特卡洛革命的一年,雷米·库洛姆(RemiCoulom)描述了蒙特卡洛方法在游戏树搜索的应用并命名为蒙特卡洛树搜索。列文特·科奇什(LeventeKocsis)和乔鲍·塞派什瓦里(CsabaSzepesvári)开发了UCT算法,西尔万·热利(SylvainGelly)等人在他们的程序MoGo中实现了UCT。2008年,MoGo在九路围棋中达到段位水平,Fuego程序开始在九路围棋中战胜实力强劲的业余棋...
· 搜索
搜索方式按是否使用启发式信息分启发式搜索盲目搜索按问题的表示方式分状态空间搜索与/或树搜索搜索策略宽度优先搜索宽度优先搜索算法是沿着树的宽度遍历树的节点,如果发现目标,则算法中止。属于盲目搜索。深度优先搜索深度优先搜索沿着树的最大深度方向生成节点并与目标节点进行比较,只有当上次访问的节点不是目标节点,而且没有其他节点可以生成的时候,才转到上次访问节点的父节点,然后搜索该节点的其他子节点。因此深度优先搜索也称为回溯搜索。它既不是完备的,也不是最优的。有时候,某些特定的问题会产生大量重复的节点。例如“八数码”问题就是这样的,当每次运用向上、向下、向左、向右移动空格的算符时,可能产生与已经产生的节点重复的节点。当再次搜索到这个重复节点时,由于应用的算符基本一致,还会产生重复,所以为了节约时间和存储空间,往往在深度优先算法中设立一个机制,用来删除这些重复的节点,以提高效率。迭代加深搜索(ID搜索)...
· 广度优先搜索
作法BFS是一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位址,彻底地搜索整张图,直到找到结果为止。BFS并不使用经验法则算法。从算法的观点,所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。一般的实现里,其邻居节点尚未被检验过的节点会被放置在一个被称为open的容器中(例如伫列或是链表),而被检验过的节点则被放置在被称为closed的容器中。(open-closed表)实现方法首先将根节点放入队列中。从队列中取出第一个节点,并检验它是否为目标。若队列为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。重复步骤2。C的实现/***ADDQ(Q,p)-pPUSH入Q*DELQ(Q)-POPQ並返回Q頂*FIRSTADJ(G,v)-v的第一個鄰接點,找不到則返回-1*NEXTADJ(G,v)-v的下...
· 搜索及拯救
种类搜索及拯救包括了多项小项,包括:地面搜索及拯救(英文:GroundSearchandRescue,缩写:GSAR),通常是于地面或者内陆水道(例如引水道)进行。传统上,此项工作通常于郊区以至荒野区域进行。城市搜索及拯救(英文:UrbanSearchandRescue,缩写:USAR),是于城市或者市区进行,通常有涉及自然灾害(例如山泥倾泻、地震、台风、洪水、受到海啸侵袭的沿海城市等)、交通意外、坍塌事故及矿道等。山岭搜索及拯救(英文:MountainSearchandRescue,缩写:MSAR),是于山上进行。海空拯救(英文:AirSeaResue),是于空中或者海上进行,需要协调飞行器及船只合作进行。战斗搜索及拯救(英文:CombatSearchandRescue,缩写:CSAR),是于战场或战区上进行。等等。历史世界上最早的搜索及拯救纪录可以追溯至1656年,一艘荷兰商业船只(V...

关于我们

关注族谱网 微信公众号,每日及时查看相关推荐,订阅互动等。

APP下载

下载族谱APP 微信公众号,每日及时查看
扫一扫添加客服微信