二叉排序树
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• ⑤二叉排序树的生成过程 • 由输入实例(5,3,7,2,4,8),根据生成二叉排序树算法生成 二叉排序树的过程【参见动画演示】 • 注意: • 输入序列决定了二叉排序树的形态。 • 二叉排序树的中序序列是一个有序序列。所以对于一个任意的关 键字序列构造一棵二叉排序树,其实质是对此关键字序列进行排序, 使其变为有序序列。"排序树"的名称也由此而来。通常将这种排序称 为树排序(Tree Sort),可以证明这种排序的平均执行时间亦为O(nlgn)。 • 对相同的输入实例,树排序的执行时间约为堆排序的2至3倍。因 此在一般情况下,构造二叉排序树的目的并非为了排序,而是用它来 加速查找,这是因为在一个有序的集合上查找通常比在无序集合上查 找更快。因此,人们又常常将二叉排序树称为二叉查找树。
二叉排序树的特点 由BST性质可得: (1) 二叉排序树中任一结点x,其左(右)子树中任一结 点y(若存在)的关键字必小(大)于x的关键字。 (2) 二叉排序树中,各结点关键字是惟一的。 注意: 实际应用中,不能保证被查找的数据集中各元素的关键 字互不相同,所以可将二叉排序树定义中BST性质(1)里的 "小于"改为"大于等于",或将BST性质(2)里的"大于"改为" 小于等于",甚至可同时修改这两个性质。 (3) 按中序遍历该树所得到的中序序列是一个递增有 序序列。
• 二叉排序树上的运算 • (1) 二叉排序树的插入和生成 • ①二叉排序树插入新结点的过程 • 在二叉排序树中插入新结点,要保证插入后仍满足 BST性质。其插入Biblioteka Baidu程是: • (a)若二叉排序树T为空,则为待插入的关键字key申 请一个新结点,并令其为根; • (b)若二叉排序树T不为空,则将key和根的关键字比 较: • (i)若二者相等,则说明树中已有此关键字key, 无须插入。 • (ii)若key<T→key,则将key插入根的左子树中。 • (iii)若key>T→key,则将它插入根的右子树中。 • 子树中的插入过程与上述的树中插入过程相同。如此 进行下去,直到将key作为一个新的叶结点的关键字插入 到二叉排序树中,或者直到发现树中已有此关键字为止。
二叉排序树的生成,是从空的二叉排序树开始,每输入一个结点数据, 就调用一次插入算法将它插入到当前已生成的二叉排序树中。生成二 叉排序树的算法如下: BSTree CreateBST(void) { //输入一个结点序列,建立一棵二叉排序树,将根结点指针返回 BSTree T=NULL; //初始时T为空树 KeyType key; scanf("%d",&key); //读人一个关键字 while(key){ //假设key=0是输人结束标志 InsertBST(&T,key); //将key插入二叉排序树T scanf("%d",&key);//读人下一关键字 } return T; //返回建立的二叉排序树的根指针 } //BSTree
就维护表的有序性而言,二叉排序树无须移 动结点,只需修改指针即可完成插入和删 除操作,且其平均的执行时间均为O(lgn), 因此更有效。二分查找所涉及的有序表是 一个向量,若有插入和删除结点的操作, 则维护表的有序性所花的代价是O(n)。当 有序表是静态查找表时,宜用向量作为其 存储结构,而采用二分查找实现其查找操 作;若有序表里动态查找表,则应选择二 叉排序树作为其存储结构。
二叉排序树插入新结点的递归算法 InsertBST(BSTNode *Tree,KeyType key) { if(*Tree==NULL) { BSTNode *p= new BSTNode; p->key=key; p->lchild=NULL; p->rchild=NULL; Tree=p; } else { if(tree->key>key) insert(tree->lchild,key); else insert(tree->rchild,key); } }
完成二叉排序树。
• (2)二叉排序树的删除 • 从二叉排序树中删除一个结点,不能 把以该结点为根的子树都删去,并且还要 保证删除后所得的二叉树仍然满足BST性质。
• 删除*p结点的过程如下: (1)首先查找p节点,如找不到则返回。 (2)若节点p没有左子树,则用右子树 的根代替被删除的节点。 (3)若节点p有左子树,则在其左子树 中找到最右节点r,将p的右子树置为r的右 子树,再用p的左子树的根节点代替被删除 的节点p.
与二分查找类似,和关键字比较的次数不超过树的深度。 (2)在二叉排序树上进行查找时的平均查找长度和二叉树的形 态有关 二分查找法查找长度为n的有序表,其判定树是惟一的。 含有n个结点的二叉排序树却不惟一。对于含有同样一组 结点的表,由于结点插入的先后次序不同,所构成的二叉 排序树的形态和深度也可能不同 【例】下图(a)所示的树,是按如下插入次序构成的: 45,24,55,12,37,53,60,28,40,70 下图(b)所示的树,是按如下插入次序构成的: 12,24,28,37,40,45,53,55,60,70
void DelBSTNode(BSTNode *Tptr,KeyType key) {//在二叉排序树*Tptr中删去关键字为key的结点 BSTNode *parent=NUll,*p=Tptr,*q; while(p){ //从根开始查找关键字为key的待删结点 if(p->key==key) break;//已找到,跳出查找循环 parent=p; //parent指向*p的双亲 p=(key<p->key)?p->lchild:p->rchild; //在关p的左或右 子树中继续找 } if(!p) return; //找不到被删结点则返回 q=p; //q记住被删结点*p
二叉排序树上的查找 ①查找递归算法 在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查 找范围的过程。 递归的查找算法: BSTNode *SearchBST(BSTree T,KeyType key) { //在二叉排序树T上查找关键字为key的结点,成功时返回该结点位置, 否则返回NUll if(T==NULL||key==T->key) //递归的终结条件 return T; //T为空,查找失败;否则成功,返回找到的结点位置 if(key<T->key) return SearchBST(T->lchild,key); else return SearchBST(T->rchild,key);//继续在右子树中查找 } //SearchBST
下图(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)二叉排序树和二分查找的比较 就平均时间性能而言,二叉排序树上的查找和二分查找 差不多。
• 下图所示的两棵树均是二叉排序树,它们 的中序序列均为有序序列:2,3,4,5,7, 8。
2 5 3
3
7
7
2
4
8
5
8
4
typedef int KeyType; //假定关键字类型为整数 Typedef struct node { //结点类型 KeyType key; //关键字项 InfoType otherinfo; //其它数据域,InfoType视应 用情况而定,下面不处理它 struct node *lchild,*rchild; //左右孩子指针 } BSTNode; typedef BSTNode * BSTree; //BSTree是二叉排 序树的类型
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
算法分析 在二叉排序树上进行查找时,若查找成功,则是从根结 点出发走了一条从根到待查结点的路径。若查找不成功, 则是从根结点出发走了一条从根到某个叶子的路径。
(1) 二叉排序树查找成功的平均查找长度 在等概率假设下,下面(a)图中二叉排序树查找成功的平 均查找长度为 ASLa=(1+2*2+3*4+4*3)/10=3 在等概率假设下,(b)图所示的树在查找成功时的平均查 找长度为: ASLb=(1+2+3+4+5+6+7+8+9+10)/10=5.5
二叉排序树
• 二叉排序树(Binary Sort Tree)又称二叉查找(搜索) 树(Binary Search Tree)。其定义为:二叉排序树 或者是空树,或者是满足如下性质的二叉树: • ①若它的左子树非空,则左子树上所有结点的值 均小于根结点的值; • ②若它的右子树非空,则右子树上所有结点的值 均大于根结点的值; • ③左、右子树本身又各是一棵二叉排序树。 • 上述性质简称二叉排序树性质(BST性质),故 二叉排序树实际上是满足BST性质的二叉树。
二叉排序树插入新结点的非递归算法 void InsertBST(BSTNode *Tptr,KeyType key) { //若二叉排序树 *Tptr中没有关键字为key,则插入,否则直接返回 BSTNode *f,*p=TPtr; //p的初值指向根结点 while(p){ //查找插入位置 if(p->key==key) return;//树中已有key,无须插入 f=p; //f保存当前查找的结点 p=(key<p->key)?p->lchild:p->rchild; //若key<p->key,则在左子树中查找,否则在右子树中查找 } //endwhile p=(BSTNode *)malloc(sizeof(BSTNode)); p->key=key; p->lchild=p->rchild=NULL; //生成新结点 if(TPtr==NULL) //原树为空 Tptr=p; //新插入的结点为新的根 else //原树非空时将新结点关p作为关f的左孩子或右孩子插入 if(key<f->key) f->lchild=p; else f->rchild=p; } //InsertBST