考研资料二叉排序树的插入分析附图解

合集下载

2-3树的插入和删除原理

2-3树的插入和删除原理

2-3树的插⼊和删除原理2-3树多路查找树2-节点,含有⼀个值和两条链接3-节点,含有两个值和三条链接所有叶⼦必须都在同⼀层次插⼊原理情况⼀空树创建⼀个⼆节点作为根节点即可情况⼆⼆节点的叶⼦节点插⼊3: 直接插⼊,将该⼆节点变为三节点即可情况三三节点的叶⼦节点 ( ⽗节点为⼆节点 )插⼊5:1.根据左⼩右⼤,5应该插到6的左边,但是6所在的节点已经是三节点,且由于叶⼦节点必须要在同⼀层次(不能单独往下延伸)2.不能够往下⾛,那就只能往上⾛,且⽗节点是⼆节点可扩展为三节点3.将扩展节点的右节点的最左元素6上移,调整叶⼦节点(结果如图)情况四三节点的叶⼦节点 ( ⽗节点为三节点 )插⼊11:1.根据数值应该插⼊到10的右边,但10所在的节点已经为三节点了,同时其⽗节点也为三节点2.继续往上找,⽗节点的⽗节点为⼆节点可扩展3.将扩展的节点的右节点的最左元素12上移4.9,10,11按照中序遍历的⽅式调整情况五三节点的叶⼦节点 ( ⽗节点及其以上均为三节点 )插⼊2:1.按照数值⼤⼩,应该插⼊到1的右边,但1所在节点及其上⾯的所有节点都是三节点了,挤不下了,这时候就要增加⾼度了2.从下往上拆,最后全部节点都变为⼆节点删除原理情况⼀删除元素所在节点是三节点直接删除,将三节点变为⼆节点即可情况⼆删除元素位于⼆节点 ( ⽗节点为⼆节点 , 右孩⼦为三节点)删除1:1.删掉12.左旋转,将4放到1所在的位置,6放到4所在的位置情况三删除元素位于⼆节点 ( ⽗节点为⼆节点 , 右孩⼦也为⼆节点)删除4:1.⾸先要知道⼀点:图中7是根节点的直接前继,根节点的直接后继则是92.将后继9拿过来帮忙,放到8的位置,8则去左边帮忙,放到7的位置(本质也是左旋)3.6,7也左旋调整情况四删除元素位于⼆节点 ( ⽗节点为三节点 )删除10:1.将⽗节点由三节点变为⼆节点2.扩展原先⽗节点的中间节点情况五满⼆叉树的时候删除如图,节点均为⼆节点删除8:1.思路与上⾯插⼊的情况五相反,所有节点都不能拆分了,那就扩⼤宽度缩⼩⼀层情况六删除的节点不是叶⼦节点 ( 删除节点右孩⼦为三节点 )删除4:1.右孩⼦最左元素上移即可2.右孩⼦变为⼆节点其余删除⾮叶⼦节点的情况处理⽅法类似,就不赘述了。

《二叉树模型》课件

《二叉树模型》课件

二叉树的分类
01 满二叉树
如果一个二叉树的每个节点都有两个子节点,则 该二叉树称为满二叉树。
02 完全二叉树
如果一个二叉树的最后一层是满的,且除了最后 一层外,其他各层的节点数达到最大,则该二叉 树称为完全二叉树。
03 平衡二叉树
平衡二叉树是一种特殊的完全二叉树,它的左右 子树的高度差不超过1。
二叉树的应用场景
详细描述
在n叉树模型中,每个节点可以拥有任意数 量的子节点,而不仅仅是两个。这种模型在 处理具有多个分支的数据结构时非常有用, 例如决策树和知识图谱。n叉树模型在搜索 、排序和数据压缩等领域有广泛应用。
B树模型
要点一
总结词
B树模型是一种自平衡的多路搜索树,用于数据库和文件系 统的索引。
要点二
详细描述
详细描述
二叉树的插入操作包括节点的添加和位置调整两个步骤。在添加节点时,需要找到合适 的位置将其插入到二叉树中,并保持二叉树的平衡性。位置调整是为了维护二叉树的性
质,确保每个节点的左子树和右子树的高度差不超过1。
插入操作的时间复杂度
总结词
插入操作的时间复杂度取决于具体的实现方式和数据结构。
详细描述
在平衡二叉树中,插入操作的时间复杂度为O(log n),其中n为二叉树中节点的数量。而在一般的二 叉树中,插入操作的时间复杂度可能达到O(n),因为可能需要遍历整棵树才能找到合适的位置插入新 节点。因此,选择合适的二叉树数据结构和算法对于提高插入操作的效率至关重要。
05
二叉树算法的应用
堆排序算法
平衡二叉树的性质:平衡二叉树具有以下性质:1)它的左右子树的高度差不超过1;2)它的左 子树和右子树都是平衡二叉树;3)它的左子树和右子树的节点数相差不超过1。

二叉排序树

二叉排序树

二叉排序树1.二叉排序树定义二叉排序树(Binary Sort Tree)或者是一棵空树;或者是具有下列性质的二叉树:(1)若左子树不空,则左子树上所有结点的值均小于根结点的值;若右子树不空,则右子树上所有结点的值均大于根结点的值。

(2)左右子树也都是二叉排序树,如图6-2所示。

2.二叉排序树的查找过程由其定义可见,二叉排序树的查找过程为:(1)若查找树为空,查找失败。

(2)查找树非空,将给定值key与查找树的根结点关键码比较。

(3)若相等,查找成功,结束查找过程,否则:①当给值key小于根结点关键码,查找将在以左孩子为根的子树上继续进行,转(1)。

②当给值key大于根结点关键码,查找将在以右孩子为根的子树上继续进行,转(1)。

3.二叉排序树插入操作和构造一棵二叉排序树向二叉排序树中插入一个结点的过程:设待插入结点的关键码为key,为将其插入,先要在二叉排序树中进行查找,若查找成功,按二叉排序树定义,该插入结点已存在,不用插入;查找不成功时,则插入之。

因此,新插入结点一定是作为叶子结点添加上去的。

构造一棵二叉排序树则是逐个插入结点的过程。

对于关键码序列为:{63,90,70,55,67,42,98,83,10,45,58},则构造一棵二叉排序树的过程如图6-3所示。

4.二叉排序树删除操作从二叉排序树中删除一个结点之后,要求其仍能保持二叉排序树的特性。

设待删结点为*p(p为指向待删结点的指针),其双亲结点为*f,删除可以分三种情况,如图6-4所示。

(1)*p结点为叶结点,由于删去叶结点后不影响整棵树的特性,所以,只需将被删结点的双亲结点相应指针域改为空指针,如图6-4(a)所示。

(2)*p结点只有右子树或只有左子树,此时,只需将或替换*f结点的*p子树即可,如图6-4(b)、(c)所示。

(3)*p结点既有左子树又有右子树,可按中序遍历保持有序地进行调整,如图6-4(d)、(e)所示。

设删除*p结点前,中序遍历序列为:① P为F的左子女时有:…,Pi子树,P,Pj,S子树,Pk,Sk子树,…,P2,S2子树,P1,S1子树,F,…。

2022考研408-二叉排序树

2022考研408-二叉排序树

2022考研408-⼆叉排序树⼆叉排序树定义⼆叉排序树或是⼀棵空树,或是具有如下性质的⼆叉树l 左⼦树若⾮空,则左⼦树所有结点的关键字必然⼩于根节点关键字l 右⼦树若⾮空,则右⼦树所有结点的关键字必然⼤于根节点关键字l 左⼦树和右⼦树均为⼆叉排序树⽰例⼆叉排序树的查找l 若⼆叉排序树为空,则查找失败l ⽐较结点关键字的值与给定值,若给定值更⼤,则查找结点的右⼦树l ⽐较结点关键字的值与给定值,若给定值更⼩,则查找结点的左⼦树⼆叉排序树的删除这⾥指删除⼆叉排序树的某⼀个结点l 若结点为叶节点,则直接删除l 若结点的度为1,也即只有⼀棵⼦树,则⽤其左孩⼦或右孩⼦代替(关键字交换),再删除这个孩⼦l 若结点有两个孩⼦,则⽤中序的直接前驱或直接后继将其代替(关键字交换),再删除这个这个直接前驱(左孩⼦的最右结点)或直接后继(右孩⼦的最左结点)⼆叉排序树的插⼊这⾥是指将将⼀个新节点插⼊到⼆叉排序树中l 若⼆叉排序树为空,则直接将新节点插⼊l 若新节点关键字⼤于当前节点的关键字,则插⼊右⼦树l 若新节点关键字⼩于当前节点的关键字,则插⼊左⼦树题⽬整理001、在⼆叉排序树中,新插⼊的关键字总是处于最底层(王道模拟四-T07-Ⅲ)吗?002、含有4个元素值均不相同的⼆叉排序树有_____种。

答:14003、含16个结点的平衡⼆叉树最⼤深度是___。

(斐波那契:a1=1, a2=2, an=an-1+an-2+1)答案整理001、答:不是的,依据⼆叉排序树的插⼊规则,只有当⼆叉排序树为空时,新的结点才能直接插⼊,否则总是会通过⽐较转⽽向其某⼀⼦树插⼊,若从查找的⾓度考虑,在⼆叉排序树中查找新节点键值,则最后查找失败的结点即为最终新节点的位置(此时将空指针视为空结点),于是新插⼊的结点总是作为新⼆叉排序树的叶⼦节点,⽽“最底层“,反映的是⼆叉树中有关”层“的概念,⼀般根节点为第⼀层,第n结点的孩⼦均处于第n+1层。

数据结构——二叉搜索树

数据结构——二叉搜索树

数据结构——二叉搜索树二叉搜索树1.介绍1.1 定义二叉搜索树(Binary Search Tree,简称BST)是一种常用的数据结构,它是一棵二叉树,其中每个节点的值都大于其左子树中的任意节点的值且小于其右子树中的任意节点的值。

1.2 特点●左子树上所有节点的值都小于根节点的值●右子树上所有节点的值都大于根节点的值●左子树和右子树都是二叉搜索树2.基本操作2.1 插入操作●若树为空,直接将新节点作为根节点●若新节点值小于当前节点值,向左子树搜索并插入●若新节点值大于当前节点值,向右子树搜索并插入2.2 查找操作●若树为空,返回空●若目标值等于当前节点值,返回当前节点●若目标值小于当前节点值,向左子树搜索●若目标值大于当前节点值,向右子树搜索2.3 删除操作●若节点为叶子节点,直接删除●若节点只有一个子节点,将子节点替代该节点●若节点有两个子节点,找到右子树中的最小节点或左子树中的最大节点替代该节点3.遍历算法3.1 前序遍历●前序遍历先访问根节点,然后递归遍历左子树和右子树3.2 中序遍历●中序遍历先递归遍历左子树,然后访问根节点,最后递归遍历右子树3.3 后序遍历●后序遍历先递归遍历左子树,然后递归遍历右子树,最后访问根节点4.平衡性4.1 AVL树AVL树是一种自平衡二叉搜索树,它保证了树的左右子树高度差不超过1。

4.2 红黑树红黑树是一种自平衡二叉搜索树,它通过对节点进行颜色标记和旋转操作来保证树的平衡性。

5.附件●相关代码范例6.法律名词及注释●本文档中未涉及法律名词及注释。

二叉排序树

二叉排序树

就维护表的有序性而言,二叉排序树无须移 动结点,只需修改指针即可完成插入和删 除操作,且其平均的执行时间均为O(lgn), 因此更有效。二分查找所涉及的有序表是 一个向量,若有插入和删除结点的操作, 则维护表的有序性所花的代价是O(n)。当 有序表是静态查找表时,宜用向量作为其 存储结构,而采用二分查找实现其查找操 作;若有序表里动态查找表,则应选择二 叉排序树作为其存储结构。
if(q->lchild) //*q的左子树非空,找*q的左子 树的最右节点r. {for(q=q->lchild;q->rchild;q=q->rchild); q->rchild=p->rchild; } if(parent->lchild==p)parent->lchild=p>lchild; else parent->rchild=p->lchild; free(p); /释放*p占用的空间 } //DelBSTNode
下图(a)所示的树,是按如下插入次序构成的: 45,24,55,12,37,53,60,28,40,70 下图(b)所示的树,是按如下插入次序构成的: 12,24,28,37,40,45,53,55,60,70
在二叉排序树上进行查找时的平均查找长度和二叉树的形态 有关: ①在最坏情况下,二叉排序树是通过把一个有序表的n 个结点依次插入而生成的,此时所得的二叉排序树蜕化为 棵深度为n的单支树,它的平均查找长度和单链表上的顺 序查找相同,亦是(n+1)/2。 ②在最好情况下,二叉排序树在生成的过程中,树的形 态比较匀称,最终得到的是一棵形态与二分查找的判定树 相似的二叉排序树,此时它的平均查找长度大约是lgn。 ③插入、删除和查找算法的时间复杂度均为O(lgn)。 (3)二叉排序树和二分查找的比较 就平均时间性能而言,二叉排序树上的查找和二分查找 差不多。

二叉搜索树-BST-查找算法-插入算法-删除算法

二叉搜索树-BST-查找算法-插入算法-删除算法

⼆叉搜索树-BST-查找算法-插⼊算法-删除算法1. 简述最近打算复习⼀下,⼏个经典的树结构,本⽂主要关注⼆叉搜索树,英⽂名称为Binary Search Tree (简称BST)。

本⽂主要总结⼆叉搜索树的查找算法、插⼊算法和删除算法。

2. 查找算法这个⽐较简单,要么找到了,要么向左,要么向右。

BSTNode* bst_search(BSTNode* node, int value) {while(node != NULL) {if(value < node->value) // 向左node = node->left;else if(value > node->value) // 向右node = node->right;else// 找到return node;}return NULL; // 失败}3. 插⼊算法这个也不难,⾸先找到插⼊的位置,要么向左,要么向右,直到找到空结点,即为插⼊位置,如果找到了相同值的结点,插⼊失败。

bool bst_insert(BSTNode*& root, int value) {BSTNode* pre = NULL;BSTNode* curr = root;while(curr != NULL) {if(value < curr->value) { // 向左pre = curr;curr = curr->left;}else if(value > curr->value) { // 向右pre = curr;curr = curr->right;}else// 失败return false;}curr = new BSTNode; // 插⼊curr->value = value;curr->left = curr->right = NULL;if(pre == NULL)root = curr;elsecurr->value < pre->value ? pre->left=curr : pre->right=curr;return true;}4. 删除算法相对查找和插⼊复杂⼀点,根据待删除结点的孩⼦情况,分三种情况:没有孩⼦,只有⼀个孩⼦,有两个孩⼦。

数据结构53:二叉排序树(二叉查找树)

数据结构53:二叉排序树(二叉查找树)

数据结构53:⼆叉排序树(⼆叉查找树)前⼏节介绍的都是有关静态查找表的相关知识,从本节开始介绍另外⼀种查找表——动态查找表。

动态查找表中做查找操作时,若查找成功可以对其进⾏删除;如果查找失败,即表中⽆该关键字,可以将该关键字插⼊到表中。

动态查找表的表⽰⽅式有多种,本节介绍⼀种使⽤树结构表⽰动态查找表的实现⽅法——⼆叉排序树(⼜称为“⼆叉查找树”)。

什么是⼆叉排序树?⼆叉排序树要么是空⼆叉树,要么具有如下特点:⼆叉排序树中,如果其根结点有左⼦树,那么左⼦树上所有结点的值都⼩于根结点的值;⼆叉排序树中,如果其根结点有右⼦树,那么右⼦树上所有结点的值都⼤⼩根结点的值;⼆叉排序树的左右⼦树也要求都是⼆叉排序树;例如,图 1 就是⼀个⼆叉排序树:图 1 ⼆叉排序树使⽤⼆叉排序树查找关键字⼆叉排序树中查找某关键字时,查找过程类似于次优⼆叉树,在⼆叉排序树不为空树的前提下,⾸先将被查找值同树的根结点进⾏⽐较,会有 3 种不同的结果:如果相等,查找成功;如果⽐较结果为根结点的关键字值较⼤,则说明该关键字可能存在其左⼦树中;如果⽐较结果为根结点的关键字值较⼩,则说明该关键字可能存在其右⼦树中;实现函数为:(运⽤递归的⽅法)BiTree SearchBST(BiTree T, KeyType key){// 如果递归过程中 T 为空,则查找结果,返回NULL;或者查找成功,返回指向该关键字的指针if (!T || key==T->data) {return T;} else if(key<T->data) {// 递归遍历其左孩⼦return SearchBST(T->lchild, key);} else {// 递归遍历其右孩⼦return SearchBST(T->rchild, key);}}⼆叉排序树中插⼊关键字⼆叉排序树本⾝是动态查找表的⼀种表⽰形式,有时会在查找过程中插⼊或者删除表中元素,当因为查找失败⽽需要插⼊数据元素时,该数据元素的插⼊位置⼀定位于⼆叉排序树的叶⼦结点,并且⼀定是查找失败时访问的最后⼀个结点的左孩⼦或者右孩⼦。

最佳二叉排序树_数据结构(C语言版)(第3版)_[共6页]

最佳二叉排序树_数据结构(C语言版)(第3版)_[共6页]
n
∑ In=1 × 0+2 × 1+4 × 2+8 × 3+…= ⎢⎣log2 i⎥⎦ i =1
9.4.1 小节介绍的平分法构造的丰满树具有最小内部路径长度。
9.5.2 最佳二叉排序树
在一棵扩充的二叉排序树中,假设内部结点由序列(a1,a2,a3,…,ai,…,an)构成,且 有 a1<a2<a3…<ai…<an。外部结点由(b0,b1,b2,…,bi,…,bn)构成,且有 b0<b1<b2…<bi…
为 K+1 的外部结点,经过这样处理后,原来的扩充二叉树就变成了一棵具有 n+1 个内部结点的扩
充二叉树,且满足:
由式(9-12)可得:
In+1=In+K En+1=En−K+2(K+1)
(9-12) (9-13)
由式(9-13)可得:
In=In+1−K
(9-14)
En+1=En+K+2 综合式(9-11)、式(9-14)和式(9-15)可得:
n
∑ ASL = p(ki )(1+ λki ) i =1
(9-9)
当每个结点具有相同的使用概率,即
P(ki )
=
1 n
时,有:
∑ ∑ ASL=
n i =1
1 n
(1
+
Байду номын сангаас
λ
ki
)
=
1 n
n i =1
(1+ λki )
本节讨论如何构造 ASL 最小的二叉排序树。
(9-10)
9.5.1 扩充二叉树

二叉排序树-插入算法

二叉排序树-插入算法

⼆叉排序树-插⼊算法1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct BTNode{5int key;6 BTNode *lchild;7 BTNode *rchild;8 }BTNode;910int BSTInsert(BTNode *&p,int key)//⽤返回值判断插⼊是否成功11 {12if(p==NULL)13 {14 p=(BTNode*)malloc(sizeof(BTNode));15 p->key=key;16 p->lchild=p->rchild=NULL;17return1;//成功插⼊18 }19else20 {21if(p->key==key) return0;//已经存在相同值的结点,插⼊失败22else23 {24if(key < p->key)25 {26return BSTInsert(p->lchild,key);//去左⼦树27 }28if(key > p->key)29 {30return BSTInsert(p->rchild,key);//去右⼦树31 }32 }33 }34 }35int BFS(BTNode*p,int maxSize)36 {37int front,rear;38 BTNode *que[maxSize];//采⽤循环队列,损失⼀个存储位置来实现队空和队满不同的判定条件39 front=rear=0;40 BTNode *q;41if(p)//⼀般默认p是存在的,这⾥以防万⼀42 {43 rear=(rear+1)%maxSize;44 que[rear]=p;//根结点⼊队45while(front!=rear)//循环队列队不空的条件(队满条件是(rear+1)%maxSize==front)(或者(front-1+maxSize)%maxSize==rear)46 {47 front=(front+1)%maxSize;48 q=que[front];//从“前⾯”出队49 printf("%d\t", q->key);50if(q->lchild)51 {52 rear=(rear+1)%maxSize;53 que[rear]=q->lchild;//左孩⼦⾮空,⼊队54 }55if(q->rchild)56 {57 rear=(rear+1)%maxSize;58 que[rear]=q->rchild;//右孩⼦⾮空,⼊队59 }60 }61 }62 }63void inorder(BTNode*p)64 {65if(p)66 {67 inorder(p->lchild);68 printf("%d\t", p->key);69 inorder(p->rchild);70 }71 }72int main(int argc, char const *argv[])73 {74int a[]={9,7,8,6,5,3,4,2,1,1,1};//有重复节点75int len=sizeof(a)/sizeof(int);76 BTNode *root=NULL;77for(int i=0;i<len;i++)//不断地插⼊结点建成⼀棵⼆叉排序树78 {79 BSTInsert(root,a[i]);80 }81// BFS(root,len);//层次遍历⽅式82 inorder(root);//中序遍历⽅式,正好配合⼆叉排序树,将其顺序打印出来83return0;84 }运⾏结果:。

二叉树常用操作(包括二叉搜索树)

二叉树常用操作(包括二叉搜索树)

⼆叉树常⽤操作(包括⼆叉搜索树)创建1个节点连接3个节点前序遍历、中序遍历、后续遍历⼆叉树(包括递归法与⾮递归法(辅助栈))清除⼆叉树在⼆叉搜索树中插⼊1个节点(和链表⼀样,注意使⽤⼆级指针,因为可能插⼊的是根节点)在⼆叉搜索树中查找1个节点在⼆叉搜索树中删除⼀个节点(和链表⼀样,注意使⽤⼆级指针,因为可能删除的是根节点)要删除的节点没有⼦节点(只需要直接将⽗节点中,指向要删除的节点指针置为null ,⽐如下图中的删除节点55)如果要删除的节点只有⼀个⼦节点(只有左⼦节点或者右⼦节点),我们只需要更新⽗节点中,指向要删除节点的指针,让它指向要删除节点的⼦节点就可以了。

⽐如图中的删除节点 13如果要删除的节点有两个⼦节点,这就⽐较复杂了。

我们需要找到这个节点的右⼦树中的最⼩节点,把它替换到要删除的节点上。

然后再删除掉这个最⼩节点,因为最⼩节点肯定没有左⼦节点(如果有左⼦结点,那就不是最⼩节点了),所以,我们可以应⽤上⾯两条规则来删除这个最⼩节点。

⽐如图中的删除节点 18。

#pragma once#include <iostream>using namespace std;struct TreeNode{int val;TreeNode* left;TreeNode* right;TreeNode(int val):val(val),left(nullptr),right(nullptr){}};// 创建⼀个节点TreeNode* CreateBinaryTreeNode(int value){TreeNode* pNode = new TreeNode(value);pNode->val = value;pNode->left = nullptr;pNode->right = nullptr;return pNode;}// 连接三个节点void ConnectTreeNodes(TreeNode* pParent, TreeNode* pLeft, TreeNode* pRight){特别注意在⼆叉树中删除⼀个节点,有3中可能情况:TreeNode.h 如下void ConnectTreeNodes(TreeNode* pParent, TreeNode* pLeft, TreeNode* pRight){ if(pParent != nullptr){pParent->left = pLeft;pParent->right = pRight;}}// 打印节点void PrintTreeNode(const TreeNode* pNode){if(pNode != nullptr){printf("value of this node is: %d\n", pNode->val);if(pNode->left != nullptr)printf("value of its left child is: %d.\n", pNode->left->val);elseprintf("left child is nullptr.\n");if(pNode->right != nullptr)printf("value of its right child is: %d.\n", pNode->right->val);elseprintf("right child is nullptr.\n");}else{printf("this node is nullptr.\n");}printf("\n");}// 打印⼆叉树(更仔细点⼉的前序遍历)void PrintTree(const TreeNode* pRoot){PrintTreeNode(pRoot);if(pRoot != nullptr){if(pRoot->left != nullptr)PrintTree(pRoot->left);if(pRoot->right != nullptr)PrintTree(pRoot->right);}}// 前序遍历⼆叉树void preOrderPrintTree(TreeNode* pRoot){if(pRoot == nullptr)return ;cout<<pRoot->val<<endl;preOrderPrintTree(pRoot->left);preOrderPrintTree(pRoot->right);}// 中序遍历⼆叉树void midOrderPrintTree(TreeNode* pRoot){if(pRoot == nullptr)return ;midOrderPrintTree(pRoot->left);cout<<pRoot->val<<endl;midOrderPrintTree(pRoot->right);}// 后续遍历⼆叉树void postOrderPrintTree(TreeNode* pRoot){if(pRoot == nullptr)return ;postOrderPrintTree(pRoot->left);postOrderPrintTree(pRoot->right);cout<<pRoot->val<<endl;}// ⾮递归法前序遍历⼆叉树(辅助栈)void preOrderPrintTreePlus(TreeNode* pRoot){if(pRoot == nullptr)if(pRoot == nullptr)return ;stack<TreeNode* > stack1;// 先⼊栈根节点stack1.push(pRoot);while(!stack1.empty()){// 获取栈顶节点TreeNode* pNode = stack1.top();cout<<pNode->val<<endl;// 出栈stack1.pop();if(pNode->right != nullptr)stack1.push(pNode->right);if(pNode->left != nullptr)stack1.push(pNode->left);}}// ⾮递归法中序遍历⼆叉树(辅助栈)void midOrderPrintTreePlus(TreeNode* pRoot){if(pRoot == nullptr)return ;stack<TreeNode* > stack1;TreeNode* pNode = pRoot;while(!stack1.empty() || pNode != nullptr){// 从根节点开始,不断访问左节点,沿路径⼊栈 while(pNode != nullptr){stack1.push(pNode);pNode = pNode->left;}// 获取栈顶节点pNode = stack1.top();cout<<pNode->val<<endl;// 出栈stack1.pop();// 对右节点执⾏相同的操作pNode = pNode->right;}}// ⾮递归法后序遍历⼆叉树(辅助栈)void postOrderPrintTreePlus(TreeNode* pRoot){ if(pRoot == nullptr)return ;stack<TreeNode* > stack1;stack<TreeNode* > stack2;TreeNode* pNode = pRoot;stack1.push(pNode);while(!stack1.empty()){pNode = stack1.top();stack1.pop();stack2.push(pNode);if(pNode->left != nullptr)stack1.push(pNode->left);if(pNode->right != nullptr)stack1.push(pNode->right);}while(!stack2.empty()){cout<<stack2.top()->val;stack2.pop();}}// 清除⼆叉树void DestroyTree(TreeNode* pRoot){if(pRoot != nullptr){TreeNode* left = pRoot->left;TreeNode* right = pRoot->right;delete pRoot;pRoot = nullptr;DestroyTree(left);DestroyTree(right);}}// ⼆叉查找树查找某⼀个节点(⼆叉搜索树)TreeNode* findNode(TreeNode* pRoot, int val){if(pRoot == nullptr)return nullptr;TreeNode* pNode = pRoot;while(pNode != nullptr){if(pNode->val < val)pNode = pNode->right;else if(pNode->val > val)pNode = pNode->left;elsereturn pNode;}return nullptr;}// ⼆叉查找树的插⼊操作(这⾥应该⽤⼆级指针,因为可能插⼊根节点)void insertTreeNode(TreeNode** pRoot, int val){if(*pRoot == nullptr){(*pRoot) = new TreeNode(val);(*pRoot)->left = nullptr;(*pRoot)->right = nullptr;return ;}TreeNode* pNode = *pRoot;while(pNode != nullptr){// 查看右⼦树if(val > pNode->val){if(pNode->right == nullptr){TreeNode* newNode = new TreeNode(val);pNode->right = newNode;return ;}pNode = pNode->right;}// 查看左⼦树else{if(pNode->left == nullptr){TreeNode* newNode = new TreeNode(val);pNode->left = newNode;return ;}pNode = pNode->left;}}return ;}// ⼆叉搜索树删除某个节点(这⾥应该⽤⼆级指针,因为可能删除根节点,这⾥就稍微有些复杂了)void deleteTreeNode(TreeNode** pRoot, int val){if(*pRoot == nullptr)return ;// deleteNode指向要删除的节点,初始化指向根节点TreeNode* deleteNode = *pRoot;// prevNode指向删除节点的⽗节点TreeNode* prevNode = nullptr;while(deleteNode != nullptr && deleteNode->val != val){prevNode = deleteNode;if(val > deleteNode->val)deleteNode = deleteNode->right;elsedeleteNode = deleteNode->left;}// 没找到这个要删除的节点,直接返回if(deleteNode == nullptr)if(deleteNode == nullptr)return ;TreeNode* pLeft = deleteNode->left;TreeNode* pRight = deleteNode->right;// 如果要删除的节点有两个⼦节点if(pLeft != nullptr && pRight != nullptr){prevNode = deleteNode;// 找到要删除节点右⼦树中最⼩节点,最⼩节点没有左⼦节点(特征) while(pRight->left != nullptr){prevNode = pRight;pRight = pRight->left;}// 修改当前删除位置的值deleteNode->val = pRight->val;// 删除的节点指向最⼩节点deleteNode = pRight;}TreeNode* child = nullptr;// 如果只有左⼦节点if(pLeft != nullptr)child = pLeft;// 如果只有右⼦节点else if(pRight != nullptr)child = pRight;// 如果是叶⼦节点,不做操作直接删除elsechild = nullptr;// 删除的是根节点if(prevNode == nullptr){*pRoot = child;}// 删除的是左⼦节点else if(prevNode->left == deleteNode){prevNode->left = child;}elseprevNode->right = child;// 最后删除节点,释放内存delete deleteNode;deleteNode = nullptr;}主函数如下#include <iostream>#include <vector>#include <stack>#include <cstring>#include <string>#include <queue>#include <algorithm>#include "TreeNode.h"#include "ListNode.h"using namespace std;int main(int argc, char* argv[]){TreeNode* pNode8 = CreateBinaryTreeNode(8); insertTreeNode(&pNode8, 1);insertTreeNode(&pNode8, 2);insertTreeNode(&pNode8, 3);insertTreeNode(&pNode8, 4);insertTreeNode(&pNode8, 5);insertTreeNode(&pNode8, 6);deleteTreeNode(&pNode8, 8);PrintTree(pNode8);return 0;}。

线索二叉树(图)

线索二叉树(图)

线索二叉树:遍历二叉树:实际上是对二叉树(非线性结构)进行的线性化操作,即以一定规则将二叉树中的结点排列成一个线性序列(先序序列、中序序列和后序序列)。

举例:图6.9所示的二叉树中的结点,按中序遍历可得到中序序列:a+b*c-d-e/f,其中‘c’的前驱为‘*’,后继为‘-’。

当以二叉链表作为二叉树的存储结构时,只能找到结点的左右孩子信息,而不能直接得到结点在任一线性序列中的前驱和后继信息,因为这种信息只有在遍历的动态过程中才能得到。

如何保存这种在遍历过程中得到的结点的前驱和后继信息呢?方法一:在二叉链表的每个结点上增加两个指针域fwd和bkwd,分别指向在依任一次序遍历时得到的前驱和后继信息。

(大大影响存储密度)方法二:利用二叉链表中的空链域来存放结点的前驱和后继信息。

(在有n个结点的二叉链表中必定存在n+1个空链域!)(不影响存储密度)为此,可以将二叉链表中的结点结构作如下修改:lchild LTag data RTag rchild其中:Ltag = 0 lchild域指示结点的左孩子1 lchild域指示结点的前驱Rtag = 0 rchild域指示结点的右孩子1 rchild域指示结点的后继我们把如此修改后的二叉链表称为二叉树的线索链表,其中指向结点前驱和后继的指针称为线索。

相应地,把添加线索后的二叉树称为线索二叉树(Threaded Binary Tree)。

对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化。

举例:图6.11(a)所示为中序线索二叉树,与其对应的中序线索链表如图 6.11(b)所示。

其中实线为指针(指向左、右子树),虚线为线索(指向前驱和后继)。

在线索树上进行遍历,只要找到序列中的第一个结点,然后依次找结点的后继直到其后继为空时而停止。

关键是如何在线索树中找结点的后继?二叉树的二叉线索存储表示:(p133-134)线索二叉树的遍历:(以中序线索二叉树为例,即中序遍历二叉线索树)算法6.5二叉树的线索化:(以中序线索化为例,即通过中序遍历建立中序线索链表)算法6.6,算法6.7。

课件类:二叉树

课件类:二叉树
② 在F中选取根结点权值最小的两棵二叉树作为左、右子树,构造 一棵新的二叉树,并且置新的二叉树的根结点的权值为其左、右 子树根结点的权值之和;
③ 在F中删除这两棵二叉树,同时将新得到的二叉树加入F中;
④ 重复②③,直到在F中只含有一棵二叉树为止。
75246 ABCDE
75 6 6
AB
E
24
11
13
7
end; end;
构造二叉排序树
主程序 Begin readln(n);
for i:=1 to n do read(a[i]);
writeln; createtree; inorder(1); End.
最优二叉树
最优二叉树(哈夫曼树、最优搜索树)
例:计算最优的判定过程
全校学生的成绩由百分制转换成五等分制,在五个等级上分布不均匀, 颁布规律如下:
构造二叉排序树的方法: ① 令a1为二叉树的根; ② 若a2<a1,则令a2为a1左子树的根结点,否则令a2为a1右子树的根结
点; ③ 对递归重复②。
构造二叉树
例:a序列为:35 40 30 90 82 32 33 37
35
30
40
32 37 90
33 82
中序遍历:30 32 33 35 37 40 82 90
百分制分数范围 0~59 60~69 70~79 80~89 90~100
分布情况%
5 15
40 30
10
现有10000个数据,以下两种判定转化过程:
<60
<80
不及格 <70
<70 <90
及格 <80
<60 中 良 优

数据结构实验报告-二叉排序树的插入和检索

数据结构实验报告-二叉排序树的插入和检索

二叉排序树的插入和检索一、实验目的(对应的中级实验的实验目的)二叉排序树的插入和检索(1)实现二叉排序树的检索,若成功,记录检索的位置信息,若不成功,记录父结点的位置信息。

(2)调用检索算法实现插入,并输出插入后的二叉排序树。

(3)实现删除算法,删除后仍然满足二叉排序树的定义,并输出删除后的结果。

要求:用链式存储实现字典结构。

提示:对二叉排序树进行中根序遍历时,获得的是排序序列。

算法思想(1)创建二叉排序树算法:如果任一结点的左子树非空,则左子树中的所有结点的关键码都小于根结点的关键码;如果任一结点的右子树非空,则右子树中的所有结点的关键码都大于根结点的关键码。

(2)二叉排序树的检索二叉排序树的检索时,若成功,记录检索的位置信息(显示检索成功的信息),若不成功,记录父结点的位置信息(显示检索不成功的信息)。

(3)二叉排序树的插入插入后的二叉树仍满足二叉排序树的定义,插入新结点的方法:1.如果二叉排序树为空,则新结点作为根结点。

2.如果二叉排序树非空,则将新结点的关键码与根结点的关键码比较,若相等表示该结点已在二叉排序树中;若小于根结点的关键码,则将新结点插入到根结点的左子树中;否则,插入到右子树中。

3.子树中的插入过程和树中的插入过程相同,如此进行下去,直到找到该结点,或者直到左或右子树非空二叉树,新结点插入成为叶子结点为止。

(4)二叉排序树的删除删除结点后的二叉树仍满足二叉排序树的定义;第一种方法:1.如果被删除结点p没有左子树,则用p的右子女代替p即可;2.否则,在p的左子树中,找出关键码最大的一个结点r (r 处于p的左子树中最右下角的位置,r一定无右子女),将r的右指针指向p的右子女,用p的左子女代替p结点。

第二种方法:1.如果被删除结点p没有左子树,则用p的右子女代替p即可;2.否则,在p的左子树中,找出关键码最大的一个结点r,用结点r代替被删除的结点p,p原来的左右子女,并且用原来r的左子女代替原来的结点r。

二叉排序树的查找、插入和删除

二叉排序树的查找、插入和删除

⼆叉排序树的查找、插⼊和删除1.⼆叉排序树⼆叉排序树(Binary Sort Tree)或者是⼀棵空树,或者是具有下列性质的⼆叉树:(1)若左⼦树不空,则左⼦树上所有结点的值均⼩于它的根结点的值;(2)若右⼦树不空,则右⼦树上所有结点的值均⼤于它的根结点的值;(3)左、右⼦树也分别为⼆叉排序树;(4)没有结点值相同的结点。

⼆叉排序树⼜称⼆叉查找树(Binary Search Tree),亦称⼆叉搜索树。

通常采⽤⼆叉链表作为⼆叉排序树的存储结构。

中序遍历⼆叉排序树可以得到关键字有序的序列,即⼀个⽆序序列可以通过构造⼆叉排序树成为有序序列,构造树的过程即为对⽆序序列排序的过程。

2.查找当⼆叉排序树不为空时,⾸先将给定值和根结点的关键字⽐较,若相等则查找成功;若给定值⼩于根结点的关键字,在左⼦树上递归查找;若给定值⼤于根结点的关键字,在右⼦树上递归查找。

代码:/** 在以T为根结点的树中,查找与给定值key相同的结点。

* 如果存在返回指向该结点的指针,否则返回空指针。

*/BiTree SearchBST1(BiTree T, TElemType key){if (!T) //空树,查找失败return NULL;else if (key == T->data) //查找成功return T;else if (key < T->data) //在左⼦树中继续查找return SearchBST1(T->lchild, key);else //在右⼦树中继续查找return SearchBST1(T->rchild, key);}3.插⼊⼆叉排序树是⼀种动态树表。

树的结构不是⼀次⽣成的,⽽是在查找过程中,当树中不存在关键字等于给定值的结点时再进⾏插⼊。

新插⼊的结点⼀定是叶⼦结点,⽽且⼀定是查找不成功时查找路径上最后⼀个结点的左孩⼦或者右孩⼦。

重写上述查找算法,以便查找不成功时,函数可以返回新结点的插⼊位置。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

p-rlink = create(key); LR_rotate(p);
}
else{
parent_p->rlink = create(key); parent_p->bf = 0;
}
}
else
/*parent_p->bf == 1,分三种情况讨论 */
{
if (key > p->key){
p->rlink = create(key); RR_rotate(p);
else { p->llink = create(key); p->bf = -1;}
return 1; /* 处理成功 */
}
else
/* 平结点的父结点不为空,分平衡因子为0,-1,1分别处理 */
{
if(parent_p->key == 0)
/*parent_p->bf == 0,分四种情况讨论*/
}
else if(parent_p->key < key && key < p->key){
p->llink = create(ky); RL_rotate(p);
}
else{
/*key < parent_p->key 的情况 */
parent_p->llink = create(key); parent_p->bf =0;
{
/* 代表parent_p, 代表p, 代表新插入结点, 其他结点*/
if(key < p->key){
p->llink = create(key); p->bf = parent_p->bf = -1;
}
else if(p->key < key && key < parent_p->key){
p->rlink = create(key); p->bf = 1; parent_p->bf = -1;
}
}
return 1; }
2013 年 12 月 25 日星期三,页码(1)
平衡二叉排序树的插入
if(平衡二叉排序树 t == Ø) {直接插入;}
if(关键码 key == p-> key) {已经存在; return 0;}
if(parent_p == Ø)
/* 父结点为空,即平衡二叉排序树中只有p一个结点 */
{
if(key > p->key) { p->rlink = create(key);p->bf = 1;}
}
else if(parent_p->key < key && key < p->key){
p->llink = create(key); p->bf = -1; parent_p->bf = 1;
}
else{
/* key > p->key */
p->rlink = create(key); p->bf = parent_p->bf = 1;
}
}
else if(parent_p->bf == -1) /*parent_p->bf == -1,分三种情况讨论 */
{
if(key < p->key){
p->llink = create(key); LL_rotate(p);
}
else if(p->key < key && key < parent_p->key){
相关文档
最新文档