二叉排序树
二叉排序树
9
第9章
第三节
二、二叉排序树(插入)
查找
动态查找表
二叉排序树是一种动态查找表
当树中不存在查找的结点时,作插入操作
新插入的结点一定是叶子结点(只需改动一个 结点的指针) 该叶子结点是查找不成功时路径上访问的最后 一个结点的左孩子或右孩子(新结点值小于或 大于该结点值) 10
第9章
第三节
查找
19
在二叉排序树中查找关 键字值等于37,88,94
3
第9章
第三节
查找
动态查找表
二、二叉排序树(查找函数)中结点结构定义 二叉排序树通常采用二叉链表的形式进行存 储,其结点结构定义如下:
typedef struct BiNode { int data; BiNode *lChild, *rChild; }BiNode,*BitTree;
4
第9章
第三节
查找
动态查找表
2、二叉排序树的定义 定义二叉排序树所有用到的变量 BitTree root; int
//查找是否成功(1--成功,0--不成功) //查找位置(表示在BisCount层中的第几个位置
BisSuccess;
int
int
BisPos;
BisCount;
//查找次数(相当于树的层数)
7
第9章
第三节
查找
动态查找表
二、二叉排序树(查找函数)
else { BisSuccess = 0; root=GetNode(k);//查找不成功,插入新的结点}
} BiNode * GetNode(int k) { BiNode *s; s = new BiNode; s->data = k; s->lChild = NULL; s->rChild = NULL; return(s);}
二叉排序树
②若*p结点只有左子树,或只有右子树,则可将*p的左子 树或右子树直接改为其双亲结点*f的左子树,即: f->1child=p->1child(或f->1child=p->rchild); free(p); *f
F *p P P1
*f
F
*f
F *p P
*f
F
Pr
P1
Pr
③若*p既有左子树,又有右子树。则:
-1 0
47
-1
47
47
0
31 69
69
25
0
47
0
25
0
47
-1 0
31
0
69
0
40
69
40
69
0
25 76
40
76
(a)
AL、BL、BR 都是空树
(b) AL、BL、BR 都是非空树
LR型调整操作示意图
2
A
-1
0
C
AR C BL CL CR AR
0 0
B BL CL S
B
A
CR
(a) 插入结点*s后失去平衡
31
0 0 -1
31
0 1
28
0
25
0 0
47
0
25
-1
47
0
25
0
31
0
16 0
28
16
28
0
16 30
30
47
(c) LR(R)型调整
RL型调整操作示意图
A B C A BR CR B BR
AL
C
AL
CL CR
数据结构 二叉排序树
9.6.2 哈希函数的构造方法
构造哈希函数的目标:
哈希地址尽可能均匀分布在表空间上——均 匀性好; 哈希地址计算尽量简单。
考虑因素:
函数的复杂度; 关键字长度与表长的关系; 关键字分布情况; 元素的查找频率。
一、直接地址法 取关键字或关键字的某个线性函数值为哈希地址 即: H(key) = key 或: H(key) = a* key + b 其中,a, b为常数。 例:1949年后出生的人口调查表,关键字是年份 年份 1949 1950 1951 … 人数 … … … …
9.4 二叉排序树
1.定义:
二叉排序树(二叉搜索树或二叉查找树) 或者是一棵空树;或者是具有如下特性的二叉树
(1) 若它的左子树不空,则左子树上所有结点的 值均小于根结点的值;
(2) 若它的右子树不空,则右子树上所有结点 的值均大于等于根结点的值; (3) 它的左、右子树也都分别是二叉排序树。
例如:
H(key)
通常设定一个一维数组空间存储记录集合,则 H(key)指示数组中的下标。
称这个一维数组为哈希(Hash)表或散列表。 称映射函数 H 为哈希函数。 H(key)为哈希地址
例:假定一个线性表为: A = (18,75,60,43,54,90,46) 假定选取的哈希函数为
hash3(key) = key % 13
H(key) = key + (-1948) 此法仅适合于: 地址集合的大小 = = 关键字集合的大小
二、数字分析法
假设关键字集合中的每个关键字都是由 s 位数 字组成 (u1, u2, …, us),分析关键字集中的全体, 并从中提取分布均匀的若干位或它们的组合作为 地址。 例如:有若干记录,关键字为 8 位十进制数, 假设哈希表的表长为100, 对关键字进行分析, 取随机性较好的两位十进制数作为哈希地址。
二叉排序树
二叉排序树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,…。
二叉树概念
点为结点i (1 i n)。则有以下关系:
若i = 1, 则 i 无双亲 若i > 1, 则 i 的双亲为i /2 若2*i <= n, 则 i 的左子女为2*i;否则,i无左子女,必定是 页结点,二叉树中i> n/2 的结点必定是页结点 若2*i+1 <= n, 则 i 的右子女为2*i+1,否则,i无右子女
层序遍历二叉树算法的框架是 • 若二叉树为空,则空操作; • 否则,根结点入队,并作为当 前结点。如队列不空,循环: 将当前结点的左右孩子入队; 做出队操作,队首元素作为当 前结点; • 最后,出队序列就是层序遍历 序列 遍历结果
表达式语法树
-+/a*efb- cd
例5-1:在二叉树中查找具有给定值的结点
}
//中序遍历*t的右子树
}
前序遍历算法
PREORDER(bitree *t) { if (t) { printf(“\t%c\n”,t->data); //访问结点*t PREORDER(t->lchild); //前序遍历*t的左子树
PREORDER(t->rchild• • • • • 结点(node) 结点的度(degree) 分支(branch)结点 叶(leaf)结点 子女(child)结点 双亲(parent)结点
结点的子树个数 度不为0的结点 度为0的结点 某结点子树的根结点 某个结点是其子树之根的 双亲
• 兄弟(sibling)结点 • 祖先(ancestor)结点
证明: 1、结点总数为度为0的结点加上度为1的结点再加上度 为2的结点: n = n0 + n1 + n2 2、另一方面,二叉树中一度结点有一个孩子,二 度结 点有二个孩子,根结点不是任何结点的孩子,因此, 结点总数为: n = n1 + 2n2 + 1 3、两式相减,得到: n0 = n2 + 1
数据结构之二叉树(BinaryTree)
数据结构之⼆叉树(BinaryTree)⽬录导读 ⼆叉树是⼀种很常见的数据结构,但要注意的是,⼆叉树并不是树的特殊情况,⼆叉树与树是两种不⼀样的数据结构。
⽬录 ⼀、⼆叉树的定义 ⼆、⼆叉树为何不是特殊的树 三、⼆叉树的五种基本形态 四、⼆叉树相关术语 五、⼆叉树的主要性质(6个) 六、⼆叉树的存储结构(2种) 七、⼆叉树的遍历算法(4种) ⼋、⼆叉树的基本应⽤:⼆叉排序树、平衡⼆叉树、赫夫曼树及赫夫曼编码⼀、⼆叉树的定义 如果你知道树的定义(有限个结点组成的具有层次关系的集合),那么就很好理解⼆叉树了。
定义:⼆叉树是n(n≥0)个结点的有限集,⼆叉树是每个结点最多有两个⼦树的树结构,它由⼀个根结点及左⼦树和右⼦树组成。
(这⾥的左⼦树和右⼦树也是⼆叉树)。
值得注意的是,⼆叉树和“度⾄多为2的有序树”⼏乎⼀样,但,⼆叉树不是树的特殊情形。
具体分析如下⼆、⼆叉树为何不是特殊的树 1、⼆叉树与⽆序树不同 ⼆叉树的⼦树有左右之分,不能颠倒。
⽆序树的⼦树⽆左右之分。
2、⼆叉树与有序树也不同(关键) 当有序树有两个⼦树时,确实可以看做⼀颗⼆叉树,但当只有⼀个⼦树时,就没有了左右之分,如图所⽰:三、⼆叉树的五种基本状态四、⼆叉树相关术语是满⼆叉树;⽽国际定义为,不存在度为1的结点,即结点的度要么为2要么为0,这样的⼆叉树就称为满⼆叉树。
这两种概念完全不同,既然在国内,我们就默认第⼀种定义就好)。
完全⼆叉树:如果将⼀颗深度为K的⼆叉树按从上到下、从左到右的顺序进⾏编号,如果各结点的编号与深度为K的满⼆叉树相同位置的编号完全对应,那么这就是⼀颗完全⼆叉树。
如图所⽰:五、⼆叉树的主要性质 ⼆叉树的性质是基于它的结构⽽得来的,这些性质不必死记,使⽤到再查询或者⾃⼰根据⼆叉树结构进⾏推理即可。
性质1:⾮空⼆叉树的叶⼦结点数等于双分⽀结点数加1。
证明:设⼆叉树的叶⼦结点数为X,单分⽀结点数为Y,双分⽀结点数为Z。
二叉排序树
就维护表的有序性而言,二叉排序树无须移 动结点,只需修改指针即可完成插入和删 除操作,且其平均的执行时间均为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)二叉排序树和二分查找的比较 就平均时间性能而言,二叉排序树上的查找和二分查找 差不多。
数据结构二叉排序树
05
13
19
21
37
56
64
75
80
88
92
low mid high 因为r[mid].key<k,所以向右找,令low:=mid+1=4 (3) low=4;high=5;mid=(4+5) div 2=4
05
13
19
low
21
37
56
64
75
80
88
92
mid high
因为r[mid].key=k,查找成功,所查元素在表中的序号为mid 的值
平均查找长度:为确定某元素在表中某位置所进行的比 较次数的期望值。 在长度为n的表中找某一元素,查找成功的平均查找长度:
ASL=∑PiCi
Pi :为查找表中第i个元素的概率 Ci :为查到表中第i个元素时已经进行的比较次数
在顺序查找时, Ci取决于所查元素在表中的位置, Ci =i,设每个元素的查找概率相等,即Pi=1/n,则:
RL型的第一次旋转(顺时针) 以 53 为轴心,把 37 从 53 的左上转到 53 的左下,使得 53 的左 是 37 ;右是 90 ,原 53 的左变成了 37 的右。 RL型的第二次旋转(逆时针)
一般情况下,假设由于二叉排序树上插入结点而失去 平衡的最小子树的根结点指针为a(即a是离插入结点最 近,且平衡因子绝对值超过1的祖先结点),则失去平衡 后进行调整的规律可归纳为下列四种情况: ⒈RR型平衡旋转: a -2 b -1 h-1 a1
2.查找关键字k=85 的情况 (1) low=1;high=11;mid=(1+11) / 2=6
05
13
19
21
二叉排序树的构造方法
二叉排序树的构造方法二叉排序树又称二叉查找树,是一种经典的数据结构,它具有快速的插入、删除和查找等操作。
在实际应用中,二叉排序树被广泛地使用,因此了解二叉排序树的构造方法至关重要。
本文将介绍二叉排序树的构造方法,帮助读者深入理解这一数据结构。
一、二叉排序树基本概念二叉排序树是一种二叉树,每个节点包含一个值,并且满足以下性质:1. 左子树上所有节点的值均小于其父节点的值;2. 右子树上所有节点的值均大于其父节点的值;3. 左右子树也分别为二叉排序树。
根据上述性质,可以得出二叉排序树的中序遍历结果为有序序列。
这一特点使得二叉排序树成为一种非常有效的数据结构,用于快速查找和排序。
二、二叉排序树的构造方法在构造二叉排序树时,一般采用递归或循环遍历的方法。
下面将分别介绍这两种构造方法。
1. 递归构造方法递归构造方法是一种常见且直观的构造二叉排序树的方式。
其基本原理为,将新节点插入到当前节点的左子树或右子树上,直至找到合适的位置。
具体流程如下所示:(1)若二叉排序树为空,直接将新节点作为根节点插入;(2)若新节点值小于当前节点值,则递归地将其插入到左子树上;(3)若新节点值大于当前节点值,则递归地将其插入到右子树上。
通过递归构造方法,可以很方便地构造出一棵满足二叉排序树性质的树。
2. 循环构造方法循环构造方法是另一种构造二叉排序树的方式,通过使用迭代的方式,逐步构建二叉排序树。
其基本思路为:(1)从根节点开始,若树为空,则直接将新节点插入为根节点;(2)若树不为空,则利用循环遍历的方式,找到新节点应插入的位置,直至找到合适的叶子节点;(3)将新节点插入到找到的叶子节点的左子树或右子树上。
循环构造方法相对于递归构造方法,更加迭代化,适合于对二叉排序树进行迭代构造和遍历。
三、二叉排序树构造方法的实现在实际编程中,可以通过使用递归或循环的方式,实现二叉排序树的构造。
下面将简要介绍二叉排序树构造方法的实现过程。
1. 递归实现递归实现二叉排序树的构造方法一般通过编写递归函数,不断地将新节点插入到当前节点的左子树或右子树上。
介绍二叉排序树的结构和特点
介绍二叉排序树的结构和特点二叉排序树,也称为二叉搜索树或二叉查找树,是一种特殊的二叉树结构,其主要特点是左子树上的节点都小于根节点,右子树上的节点都大于根节点。
在二叉排序树中,每个节点都存储着一个关键字,而且所有的关键字都不相同。
二叉排序树的结构如下:1.根节点:二叉排序树的根节点是整个树的起始点,其关键字是最大的。
2.左子树:根节点的左子树包含着小于根节点关键字的所有节点,且左子树本身也是一个二叉排序树。
3.右子树:根节点的右子树包含着大于根节点关键字的所有节点,且右子树本身也是一个二叉排序树。
二叉排序树的特点如下:1.有序性:二叉排序树的最重要特点是有序性。
由于左子树上的节点都小于根节点,右子树上的节点都大于根节点,所以通过中序遍历二叉排序树,可以得到一个有序的序列。
2.快速查找:由于二叉排序树是有序的,所以可以利用二叉排序树进行快速查找操作。
对于给定的关键字,可以通过比较关键字与当前节点的大小关系,逐步缩小查找范围,最终找到目标节点。
3.快速插入和删除:由于二叉排序树的有序性,插入和删除操作比较简单高效。
插入操作可以通过比较关键字的大小关系,找到合适的位置进行插入。
删除操作可以根据不同情况,分为三种情况处理:删除节点没有子节点、删除节点只有一个子节点和删除节点有两个子节点。
4.可以用于排序:由于二叉排序树的有序性,可以利用二叉排序树对一组数据进行排序。
将数据依次插入二叉排序树中,然后再通过中序遍历得到有序序列。
二叉排序树的优缺点如下:1.优点:(1)快速查找:通过二叉排序树可以提供快速的查找操作,时间复杂度为O(log n)。
(2)快速插入和删除:由于二叉排序树的有序性,插入和删除操作比较简单高效。
(3)可以用于排序:通过二叉排序树可以对一组数据进行排序,时间复杂度为O(nlog n)。
2.缺点:(1)受数据分布影响:如果数据分布不均匀,可能导致二叉排序树的高度增加,从而降低了查找效率。
(2)不适合大规模数据:对于大规模数据,二叉排序树可能会导致树的高度过高,从而影响了查找效率。
数据结构:第9章 查找2-二叉树和平衡二叉树
return(NULL); else
{if(t->data==x) return(t);
if(x<(t->data) return(search(t->lchild,x));
else return(search(t->lchild,x)); } }
——这种既查找又插入的过程称为动态查找。 二叉排序树既有类似于折半查找的特性,又采用了链表存储, 它是动态查找表的一种适宜表示。
注:若数据元素的输入顺序不同,则得到的二叉排序树形态 也不同!
讨论1:二叉排序树的插入和查找操作 例:输入待查找的关键字序列=(45,24,53,45,12,24,90)
二叉排序树的建立 对于已给定一待排序的数据序列,通常采用逐步插入结点的方 法来构造二叉排序树,即只要反复调用二叉排序树的插入算法 即可,算法描述为: BiTree *Creat (int n) //建立含有n个结点的二叉排序树 { BiTree *BST= NULL;
for ( int i=1; i<=n; i++) { scanf(“%d”,&x); //输入关键字序列
– 法2:令*s代替*p
将S的左子树成为S的双亲Q的右子树,用S取代p 。 若C无右子树,用C取代p。
例:请从下面的二叉排序树中删除结点P。
F P
法1:
F
P
C
PR
C
PR
CL Q
CL QL
Q SL
S PR
QL S
SL
法2:
F
PS
C
PR
CL Q
QL SL S SL
数据结构 -第12周查找第3讲-二叉排序树.pdf
以二叉树或树作为表的组织形式,称为树表,它是一类动态查找表,不仅适合于数据查找,也适合于表插入和删除操作。
常见的树表:二叉排序树平衡二叉树B-树B+树9.3.1 二叉排序树二叉排序树(简称BST)又称二叉查找(搜索)树,其定义为:二叉排序树或者是空树,或者是满足如下性质(BST性质)的二叉树:❶若它的左子树非空,则左子树上所有节点值(指关键字值)均小于根节点值;❷若它的右子树非空,则右子树上所有节点值均大于根节点值;❸左、右子树本身又各是一棵二叉排序树。
注意:二叉排序树中没有相同关键字的节点。
二叉树结构满足BST性质:节点值约束二叉排序树503080209010854035252388例如:是二叉排序树。
66不试一试二叉排序树的中序遍历序列有什么特点?二叉排序树的节点类型如下:typedef struct node{KeyType key;//关键字项InfoType data;//其他数据域struct node*lchild,*rchild;//左右孩子指针}BSTNode;二叉排序树可看做是一个有序表,所以在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查找范围的过程。
1、二叉排序树上的查找Nk< bt->keybtk> bt->key 每一层只和一个节点进行关键字比较!∧∧p查找到p所指节点若k<p->data,并且p->lchild=NULL,查找失败。
若k>p->data,并且p->rchild=NULL,查找失败。
查找失败的情况加上外部节点一个外部节点对应某内部节点的一个NULL指针递归查找算法SearchBST()如下(在二叉排序树bt上查找关键字为k的记录,成功时返回该节点指针,否则返回NULL):BSTNode*SearchBST(BSTNode*bt,KeyType k){if(bt==NULL||bt->key==k)//递归出口return bt;if(k<bt->key)return SearchBST(bt->lchild,k);//在左子树中递归查找elsereturn SearchBST(bt->rchild,k);//在右子树中递归查找}在二叉排序树中插入一个关键字为k的新节点,要保证插入后仍满足BST性质。
二叉树
平衡树——特点:所有结点左右子树深度差≤1排序树——特点:所有结点―左小右大字典树——由字符串构成的二叉排序树判定树——特点:分支查找树(例如12个球如何只称3次便分出轻重)带权树——特点:路径带权值(例如长度)最优树——是带权路径长度最短的树,又称Huffman树,用途之一是通信中的压缩编码。
1.1 二叉排序树:或是一棵空树;或者是具有如下性质的非空二叉树:(1)若左子树不为空,左子树的所有结点的值均小于根的值;(2)若右子树不为空,右子树的所有结点均大于根的值;(3)它的左右子树也分别为二叉排序树。
例:二叉排序树如图9.7:二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。
中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。
每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。
搜索,插入,删除的复杂度等于树高,期望O(logn),最坏O(n)(数列有序,树退化成线性表).虽然二叉排序树的最坏效率是O(n),但它支持动态查询,且有很多改进版的二叉排序树可以使树高为O(logn),如SBT,AVL,红黑树等.故不失为一种好的动态排序方法.2.2 二叉排序树b中查找在二叉排序树b中查找x的过程为:1. 若b是空树,则搜索失败,否则:2. 若x等于b的根节点的数据域之值,则查找成功;否则:3. 若x小于b的根节点的数据域之值,则搜索左子树;否则:4. 查找右子树。
[cpp]view plaincopyprint?1.Status SearchBST(BiTree T, KeyType key, BiTree f, BiTree &p){2. //在根指针T所指二叉排序樹中递归地查找其关键字等于key的数据元素,若查找成功,3. //则指针p指向该数据元素节点,并返回TRUE,否则指针P指向查找路径上访问的4. //最好一个节点并返回FALSE,指针f指向T的双亲,其初始调用值为NULL5. if(!T){ p=f; return FALSE;} //查找不成功6. else if EQ(key, T->data.key) {P=T; return TRUE;} //查找成功7. else if LT(key,T->data.key)8. return SearchBST(T->lchild, key, T, p); //在左子树继续查找9. else return SearchBST(T->rchild, key, T, p); //在右子树继续查找10.}2.3 在二叉排序树插入结点的算法向一个二叉排序树b中插入一个结点s的算法,过程为:1. 若b是空树,则将s所指结点作为根结点插入,否则:2. 若s->data等于b的根结点的数据域之值,则返回,否则:3. 若s->data小于b的根结点的数据域之值,则把s所指结点插入到左子树中,否则:4. 把s所指结点插入到右子树中。
二叉排序树课程设计
二叉排序树课程设计一、课程目标知识目标:1. 学生能够理解二叉排序树的基本概念和性质,掌握其结构特点和应用场景。
2. 学生能够掌握二叉排序树的插入、删除和查找操作,并了解其时间复杂度。
3. 学生能够理解二叉排序树与其他排序算法的关系,了解其在排序中的应用。
技能目标:1. 学生能够运用所学知识,独立构建二叉排序树,并实现插入、删除和查找功能。
2. 学生能够分析二叉排序树的性能,对其进行优化,提高排序效率。
3. 学生能够运用二叉排序树解决实际问题,如数据排序、查找等。
情感态度价值观目标:1. 学生通过学习二叉排序树,培养对数据结构和算法的兴趣,提高解决问题的能力。
2. 学生在学习过程中,学会合作、交流,培养团队精神和共享意识。
3. 学生能够认识到二叉排序树在实际应用中的价值,激发对计算机科学的热爱。
本课程针对高中年级学生,课程性质为理论与实践相结合。
在教学过程中,注重启发式教学,引导学生主动探究、实践。
根据学生特点和教学要求,课程目标具体、可衡量,以便学生和教师能够清晰地了解课程的预期成果。
课程目标的分解为具体的学习成果,为后续的教学设计和评估提供依据。
二、教学内容1. 引入二叉排序树的概念,讲解其定义、性质和基本操作。
- 理解二叉树的基础知识,回顾二叉树的遍历方法。
- 介绍二叉排序树的定义,阐述其特点及应用场景。
- 分析二叉排序树的性质,如二叉排序树的中序遍历结果为有序序列。
2. 探讨二叉排序树的构建、插入、删除和查找操作。
- 讲解二叉排序树的构建方法,学会从无序数据建立二叉排序树。
- 分析插入、删除和查找操作的步骤,理解它们的时间复杂度。
- 举例说明如何利用二叉排序树实现数据排序和查找。
3. 分析二叉排序树的性能及优化方法。
- 探讨二叉排序树的高度、平衡因子等性能指标。
- 介绍常见的优化方法,如平衡二叉树(AVL树)和红黑树。
4. 实践环节:二叉排序树的应用。
- 设计实践题目,让学生动手实现二叉排序树的基本操作。
二叉排序树课程设计
二叉排序树课程设计一、课程目标知识目标:1. 理解二叉排序树的概念和特点;2. 掌握二叉排序树的插入、删除和查找操作;3. 能够分析二叉排序树的时间复杂度;4. 了解二叉排序树在实际应用中的优势。
技能目标:1. 能够手动构建二叉排序树并进行基本操作;2. 能够运用编程语言实现二叉排序树的基本功能;3. 能够分析并解决二叉排序树相关的问题;4. 能够运用二叉排序树解决实际排序和查找问题。
情感态度价值观目标:1. 培养学生对数据结构和算法的兴趣,激发学习热情;2. 培养学生的逻辑思维能力和问题解决能力;3. 培养学生的团队协作意识,学会与他人共同分析、解决问题;4. 培养学生严谨的科学态度,注重算法的正确性和效率。
课程性质:本课程为计算机科学领域的数据结构与算法课程,旨在让学生掌握二叉排序树的基本概念和操作,提高学生的编程能力和逻辑思维能力。
学生特点:学生具备基本的计算机知识和编程基础,对数据结构有一定了解,但对二叉排序树的认识可能较浅。
教学要求:结合学生特点,采用讲解、实践和讨论相结合的教学方法,使学生在理解二叉排序树理论知识的基础上,能够动手实践并解决实际问题。
在教学过程中,注重培养学生的自主学习能力和团队合作精神,提高学生的综合素质。
通过本课程的学习,使学生能够达到上述课程目标,为后续相关课程打下坚实基础。
二、教学内容1. 引入二叉排序树的概念,阐述其定义、性质和应用场景;- 教材章节:第三章第一节“二叉排序树的定义和性质”2. 讲解二叉排序树的插入、删除、查找操作及其实现方法;- 教材章节:第三章第二节“二叉排序树的操作”3. 分析二叉排序树的性能特点,包括时间复杂度和空间复杂度;- 教材章节:第三章第三节“二叉排序树的性能分析”4. 介绍二叉排序树在实际应用中的优势,如排序、查找等;- 教材章节:第三章第四节“二叉排序树的应用”5. 结合实例,让学生动手实践二叉排序树的构建和操作;- 教材章节:第三章实例分析与编程练习6. 总结二叉排序树的特点和适用场景,与其他排序方法进行对比;- 教材章节:第三章总结与拓展教学进度安排:1. 第1课时:引入二叉排序树的概念、性质和应用场景;2. 第2课时:讲解二叉排序树的插入、删除、查找操作;3. 第3课时:分析二叉排序树的性能特点;4. 第4课时:介绍二叉排序树在实际应用中的优势;5. 第5课时:结合实例,学生动手实践二叉排序树的构建和操作;6. 第6课时:总结二叉排序树,与其他排序方法进行对比。
头歌二叉排序表的基本操作
头歌二叉排序表的基本操作一、概述二叉排序树,也称为二叉搜索树(Binary Search Tree, BST),是一种特殊的二叉树,其中每个节点都满足以下性质:对于任意节点,其左子树中所有节点的值都小于该节点的值,而其右子树中所有节点的值都大于该节点的值。
这种特性使得二叉排序树成为一种非常有效的数据结构,用于在各种算法中实现快速查找、插入和删除操作。
二、基本操作1. 插入操作插入操作是二叉排序树中最常用的操作之一。
其基本步骤如下:(1)创建一个新节点,并将要插入的值赋给该节点。
(2)如果二叉排序树为空,则将新节点作为根节点。
(3)否则,从根节点开始比较新节点的值与当前节点的值。
如果新节点的值小于当前节点的值,则将新节点插入到当前节点的左子树中;否则,将新节点插入到当前节点的右子树中。
(4)重复步骤3,直到找到一个空位置来插入新节点。
2. 删除操作删除操作是二叉排序树中比较复杂的操作之一。
其基本步骤如下:(1)找到要删除的节点。
如果找不到要删除的节点,则无法进行删除操作。
(2)如果找到要删除的节点,则将其从树中删除。
如果该节点只有一个子节点,则直接删除该节点;如果该节点有两个子节点,则可以选择将其中的一个子节点“提升”到该节点的位置,然后删除该子节点。
在提升子节点时,需要考虑子节点的值与要删除的节点的值之间的关系,以确保二叉排序树的性质不变。
(3)如果被提升的子节点仍然包含要删除的节点,则需要重复步骤2,直到找到要删除的节点并将其删除。
3. 查找操作查找操作用于在二叉排序树中查找指定的值。
其基本步骤如下:(1)从根节点开始,比较当前节点的值与要查找的值。
如果它们相等,则查找成功,返回当前节点的位置。
(2)如果当前节点的值大于要查找的值,则进入当前节点的左子树中进行查找;否则进入当前节点的右子树中进行查找。
(3)重复步骤2,直到找到要查找的值或者搜索路径上的所有节点都已访问过。
如果最终没有找到要查找的值,则返回空指针。
数据结构_第9章_查找2-二叉树和平衡二叉树
F
PS
C
PR
CL Q
QL SL S SL
10
3
18
2
6 12
6 删除10
3
18
2
4 12
4
15
15
三、二叉排序树的查找分析
1) 二叉排序树上查找某关键字等于给定值的结点过程,其实 就是走了一条从根到该结点的路径。 比较的关键字次数=此结点的层次数; 最多的比较次数=树的深度(或高度),即 log2 n+1
-0 1 24
0 37
0 37
-0 1
需要RL平衡旋转 (绕C先顺后逆)
24
0
-012
13
3573
0
01
37
90
0 53 0 53
0 90
作业
已知如下所示长度为12的表:
(Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct, Nov, Dec)
(1) 试按表中元素的顺序依次插入一棵初始为空的二叉 排序树,画出插入完成之后的二叉排序树,并求其在 等概率的情况下查找成功的平均查找长度。
2) 一棵二叉排序树的平均查找长度为:
n i1
ASL 1
ni Ci
m
其中:
ni 是每层结点个数; Ci 是结点所在层次数; m 为树深。
最坏情况:即插入的n个元素从一开始就有序, ——变成单支树的形态!
此时树的深度为n ; ASL= (n+1)/2 此时查找效率与顺序查找情况相同。
最好情况:即:与折半查找中的判ห้องสมุดไป่ตู้树相同(形态比较均衡) 树的深度为:log 2n +1 ; ASL=log 2(n+1) –1 ;与折半查找相同。
二叉排序树的判定代码
二叉排序树的判定代码1.引言概述部分的内容可以介绍二叉排序树及其重要性。
可以参考以下示范:1.1 概述二叉排序树(Binary Search Tree,BST)是一种重要的数据结构,在计算机科学领域具有广泛的应用。
它是一种基于二叉树的数据结构,其中每个节点都包含一个键及其对应的值。
通过比较节点的键,可以将整个树组织为一个有序的结构。
二叉排序树具有以下特性:- 左子树中的所有节点的键值小于根节点的键值。
- 右子树中的所有节点的键值大于根节点的键值。
- 左、右子树也都是二叉排序树。
二叉排序树的重要性主要体现在以下几个方面:首先,二叉排序树可以高效地支持搜索和插入操作。
由于二叉排序树的有序性质,我们可以使用二叉树的搜索算法快速地找到特定键对应的值。
而插入操作也是非常高效的,只需要根据节点的键值逐层比较并插入到合适的位置即可。
其次,二叉排序树可以支持有序遍历操作。
有序遍历是指按照节点的键值升序或降序的方式遍历整棵树。
这种遍历方式对于需要按照一定顺序处理数据的场景非常有用,比如对于某种排序算法的输入数据进行预处理。
此外,二叉排序树还可以支持高效的删除操作。
删除一个节点时,我们可以根据节点的键值快速找到该节点,并根据不同情况进行删除操作。
相比其他数据结构,二叉排序树的删除操作更加简洁高效。
综上所述,二叉排序树是一种重要的数据结构,具有高效的搜索、插入、遍历和删除等操作,对于解决许多实际问题具有重要作用。
本文将介绍二叉排序树的定义以及判定二叉排序树的算法,希望能对读者深入理解和应用二叉排序树提供帮助。
1.2 文章结构文章结构部分的内容可以包括以下内容:文章结构部分旨在介绍本文的整体结构,并简要描述各个部分的内容安排。
本文将按照以下结构进行叙述:1. 引言:本部分旨在引入文章的主题和背景,并对问题进行概述。
首先介绍二叉排序树及其重要性,然后简要介绍本文的目的和组织结构。
2. 正文:本部分是文章的核心,详细介绍了二叉排序树的定义和判定算法。
二叉排序树与文件操作的设计与实现
一、二叉排序树的基本概念二叉排序树又称为二叉查找树,是一种特殊的二叉树。
它的定义是:若左子树不空,则左子树上所有节点的值均小于它的根节点的值;若右子树不空,则右子树上所有节点的值均大于它的根节点的值;左、右子树也分别为二叉排序树。
二叉排序树的中序遍历结果是递增的。
二、二叉排序树的操作1. 查找操作在二叉排序树中查找一个值为key的节点时,可以按照以下步骤进行:1)若树为空,则查找失败;2)若树的根节点值等于key,则查找成功;3)若key小于树的根节点值,则在左子树中递归查找;4)若key大于树的根节点值,则在右子树中递归查找。
2. 插入操作插入一个新节点时,需要按照以下步骤进行:1)若树为空,则将新节点直接插入为根节点;2)若key小于树的根节点值,则将新节点插入到左子树中;3)若key大于树的根节点值,则将新节点插入到右子树中。
3. 删除操作删除一个值为key的节点时,需要考虑以下几种情况:1)若待删除节点无子节点,则直接删除;2)若待删除节点只有一个子节点,则将子节点替换为该节点;3)若待删除节点有两个子节点,则需要找到它的前驱或后继节点来替换。
三、文件操作的设计与实现1. 文件操作的基本概念文件操作是指对计算机文件进行的各种处理操作,包括创建、打开、读取、写入、关闭等。
在实际开发中,文件操作是非常常见的操作之一。
2. 文件操作的流程在进行文件操作时,一般需要按照以下流程进行:1)打开文件:通过指定文件名和打开方式,打开要进行操作的文件;2)读取或写入数据:根据需要进行读取或写入文件的操作;3)关闭文件:在操作完成后,需要关闭文件,释放资源。
3. 文件操作的设计与实现在进行文件操作的设计与实现时,需要考虑以下几点:1)文件存在性检查:在进行打开操作前,需要对文件是否存在进行检查,避免因文件不存在而导致的错误;2)错误处理:在进行文件操作时,需要对可能发生的错误进行处理,保证程序的稳定性和健壮性;3)资源释放:在操作完成后,需要及时关闭文件,并释放相关资源,以避免资源泄露。
二叉排序树的概念
二叉排序树的概念什么是二叉排序树二叉排序树(Binary Search Tree),也称为二叉查找树、二叉搜索树,是一种特殊的二叉树结构。
它具有以下特点:1.每个节点最多有两个子节点;2.左子节点的值小于等于当前节点的值,右子节点的值大于等于当前节点的值;3.每个子树也都是二叉排序树。
这个特点使得二叉排序树可以用于高效地查找、插入和删除节点,是一种常见且重要的数据结构。
二叉排序树的性质二叉排序树具有以下性质:1.左子树中所有节点的值均小于根节点的值;2.右子树中所有节点的值均大于根节点的值;3.左右子树也都是二叉排序树。
由这些性质可以得出,对于一个二叉排序树,进行中序遍历,会得到一个递增的有序序列。
二叉排序树的操作1. 插入节点要插入一个节点到二叉排序树中,需要遵循以下步骤:1.如果树为空,将根节点设置为要插入的节点;2.如果要插入的节点值小于当前节点的值,且当前节点的左子节点为空,则将要插入的节点作为当前节点的左子节点;3.如果要插入的节点值大于等于当前节点的值,且当前节点的右子节点为空,则将要插入的节点作为当前节点的右子节点;4.如果要插入的节点值小于当前节点的值,且当前节点的左子节点不为空,则将当前节点的左子节点作为新的当前节点,重复步骤2;5.如果要插入的节点值大于等于当前节点的值,且当前节点的右子节点不为空,则将当前节点的右子节点作为新的当前节点,重复步骤3。
2. 删除节点要删除二叉排序树中的一个节点,需要遵循以下步骤:1.首先找到要删除的节点,如果节点不存在,则无需删除;2.如果要删除的节点没有子节点,直接删除该节点;3.如果要删除的节点只有一个子节点,将子节点替代要删除的节点;4.如果要删除的节点有两个子节点,需要找到其后继节点或前驱节点来替代它。
通常选择后继节点,即右子树中的最小节点,将后继节点的值替代要删除的节点的值,然后删除后继节点。
3. 查找节点要在二叉排序树中查找一个节点,需要从根节点开始,根据节点的值与目标值的大小关系,递归地搜索左子树或右子树,直到找到目标节点或搜索到空位置为止。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
6.5 二叉排序树★3◎41.二叉排序树定义二叉排序树(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,…。
②P为F的右子女时有:…,F,Pi子树,P,Pj,S子树,Pk,Sk子树,…,P2,S2子树,P1,S1子树,…。
则删除*p结点后,中序遍历序列应为:①P为F的左子女时有:…,Pi子树,Pj,S子树,Pk,Sk子树,…,P2,S2子树,P1,S1子树,F,…。
② P为F的右子女时有:…,F,Pi子树,Pj,S子树,Pk,Sk子树,…,P2,S2子树,P1,S1子树,…。
有两种调整方法:①直接令Pi为*f相应的子树,以Pr为Pi中序遍历的最后一个结点Pk的右子树。
②令*p结点的直接前驱Pr或直接后继(对Pi子树中序遍历的最后一个结点Pk)替换*p结点,再按(2)的方法删去Pr或Pk。
【算法分析】对给定序列建立二叉排序树,若左右子树均匀分布,则其查找过程类似于有序表的折半查找。
但若给定序列原本有序,则建立的二叉排序树就蜕化为单链表,其查找效率和顺序查找一样。
因此,对均匀的二叉排序树进行插入或删除结点后,应进行调整,使其依然保持均匀。
3.2.5 二叉排序树在这一部分我们要掌握的是二叉排序树的概念、查找、插入和删除操作。
在以下的知识点中,二叉排序树的删除相对于其他知识点要复杂一些,但只要掌握了规则,题目还是很容易解决的。
下面我们先分别给出各部分的介绍及算法实现,再对一些典型题目进行解析。
(1)二叉排序树二叉排序树是一种常用的动态查找表,下面首先给出它的非递归形式。
二叉排序树是一棵二叉树,它或者为空,或者具有如下性质:①任一非终端结点若有左孩子,则该结点的关键字值大于其左孩子结点的关键字值。
②任一非终端结点若有右孩子,则该结点的关键字值小于其右孩子结点的关键字值。
二叉排序树也可以用递归的形式定义,即二叉排序树是一棵树,它或者为空,或者具有如下性质:①若它的左子树非空,则其左子树所有结点的关键字值均小于其根结点的关键字值。
②若它的右子树非空,则其右子树所有结点的关键字值均大于其根结点的关键字值。
③它的左右子树都是二叉排序树。
例如,由关键字值序列(62,15,68,46,65,12,57,79,35)构成的一棵二叉排序树如图3-38所示。
如果对上述二叉排序树进行中序遍历可以得到一个关键字有序序列(12,15,35,46,57,62,65,68,79),这是二叉排序树的一个重要特征,也正是由此将其称为"二叉排序树"。
(2)二叉排序树的查找二叉排序树的结构定义中可看到:一棵非空二叉排序树中根结点的关键字值大于其左子树上所有结点的关键字值,而小于其右子树上所有结点的关键字值。
因此在二叉排序树中查找一个关键字值为k的结点的基本思想是:用给定值k与根结点关键字值比较,如果k小于根结点的值,则要找的结点只可能在左子树中,所以继续在左子树中查找,否则将继续在右子树中查找,依此方法,查找下去,至直查找成功或查找失败为止。
二叉排序树查找的过程描述如下:①若二叉树为空树,则查找失败;②将给定值k与根结点的关键字值比较,若相等,则查找成功;③若根结点的关键字值小于给定值k,则在左子树中继续搜索;④否则,在右子树中继续查找。
假定二叉排序树的链式存储结构的类型定义如下:1typedef struct linklist{2keytype key;3anytype otherelem;4struct linklist*lchild;5struct linklist*rchild;6}Bin_Sort_Tree_Linklist,*Bin_Sort_Tree;二叉排序树查找过程的描述是一个递归过程,若用链式存储结构存储,其查找操作的递归算法如下所示:7Bin_Sort_Tree_Linklist*bt_search(Bin_Sort_Tree bt,keytype k)8{∥在根指针为bt的二叉排序树上查找一个关键字值为k的结点,9∥若查找成功返回指向该结点的指针,否则返回空指针10if(bt=NULL)‖(bt->key==k)return bt;11else if(k<bt->key)return bt_search(bt->lchild,k);12∥在左子树中搜索13else return bt_search(bt->rchild,k);//在右子树中搜索14}这个过程也可以用非递归算法实现,算法描述如下:15Bin_Sort_Tree_Linklist*bt_search1(Bin_Sort_Tree bt,keytype k)16{17p=bt;∥指针p指向根结点,搜索从根结点开始18while(p!=NULL && p->key!=k)19{20if(k<p->key)p=p->lchild;21else p=p->rchild;22}23return(p);24}3)二叉排序树的插入在一棵二叉排序树中插入一个结点可以用一个递归的过程实现。
若二叉排序树为空,则新结点作为二叉排序树的根结点。
否则,若给定结点的关键字值小于根结点关键字值,则插入在左子树上;若给定结点的关键字值大于根结点的值,则插入在右子树上。
下面是二叉排序树插入操作的递归算法。
1void bt_insert1(Bin_Sort_Tree*bt,Bin_Sort_Tree_Linklist*pn)2{∥在以bt为根的二叉排序树上插入一个由指针pn指向的新的结点3if(*bt=NULL)*bt=pn;4else if(*bt->key>pn->key)bt_insert 1(&(*bt->lchild),pn);5else if(*bt->key<pn->key)bt_insert1(&(*bt->rchild),pn);6}这个算法也可以用非递归的形式实现,如下所示:7void bt_insert 2(Bin_Sort_Tree*bt,8Bin_Sort_Tree_Linklist*pn)9{10p=bt;11while(p!=NULL && p->key!=pn->key)12{13 q=p;14if(p->key>pn->key)p=p->lchild;15else p=p->rchild;16}17if(p=NULL){18if(q->key>pn->key)q->lchild=pn;19else q->rchild=pn->key;20}21}利用二叉排序树的插入算法,可以很容易地实现创建二叉排序树的操作,其基本思想为:由一棵空二叉树开始,经过一系列的插入操作生成一棵二叉排序树。
例如,由结点关键字序列(62,15,68,46,65,12,57,79,35)构造二叉排序树的过程为:从空二叉树开始,依次将每个结点插入到二叉排序树中,在插入每个结点时都是从根结点开始搜索插入位置,找到插入位置后,将新结点作为叶子结点插入,经过9次的插入操作,建成由这9个结点组成的二叉排序树。
创建二叉排序树的算法如下:22Bin_Sort_Tree_Linklist*bt_bulid(Bin_Sort_Tree a,int n)23{∥在数组a的a[1]~a[n]24单元中存放着将要构成二叉排序树的n个结点内容25bt=NULL;26for(i=1;i<=n;i++)27{28p=(Bin_Sort_Tree_Linklist*)malloc29(sizeof(Bin_Sort_Tree_Linklist));30p->key=a[i].key;31p->otherelem=a[i].otherelem;;32p->lchile=NULL;33p->rchile=NULL;34bt_insert1(&bt,p);35}36return(bt);37}(4)二叉排序树的删除下面分四种情况讨论一下如何确保从二叉树中删除一个结点后,不会影响二叉排序树的性质:①若要删除的结点p为叶子结点,可以直接进行删除。
②若要删除结点p有右子树,但无左子树,可用其右子树的根结点取代要删除结点的位置。
③若要删除结点p有左子树,但无右子树,可用其左子树的根结点取代要删除结点的位置,与步骤②类似。
④若要删除结点p的左右子树均非空,则在其左子树中找到最右结点r来代替被删的结点(即将r所指结点的右指针置成p所指结点的右子树的根,然后用p所指结点的左子树的根结点代替被删的p所指结点)。