数据结构之二叉排序树
来源:互联网 发布:淘宝 国际米兰球衣 编辑:程序博客网 时间:2024/05/17 07:28
小目录
1.前言
2.二叉排序树的查找
3.二叉排序树的插入
4.二叉排序树的删除
5.二叉排序树的查找分析
1.前言
前面的一篇博客介绍了静态查找(链接),接下来将介绍动态查找。对动态查找经常进行的操作有:(1)查找某个特定的数据元素中是否存在查找表中;(2)检索某个特定元素的各种属性(3)在查找表插入一个元素;(4)在查找表中删去某个特定元素。
二叉排序树(Binary Sort Tree)或者是一棵空树;或者是具有下列性质的二叉树:
- 若左子树不空,则左子树上所有结点的值均小于根结点的值;若右子树不空,则右子树上所有结点的值均大于根结点的值。
- 左右子树也都是二叉排序树。
二叉排序树的数据存储结构如下:
typedef int TElemType;//二叉查找树的节点结构typedef struct BiTNode {TElemType data;struct BiTNode *lchild;struct BiTNode *rchild;}*BiTree;
二叉排序树的查找:
从其定义可见,二叉排序树的查找过程为:
- 若查找树为空,查找失败。
- 查找树非空,将给定值key 与查找树的根结点关键码比较。
- 若相等,查找成功,结束查找过程,否则,
a.当给key 小于根结点关键码,查找将在以左孩子为根的子树上继续进行,转①
b.当给key 大于根结点关键码,查找将在以右孩子为根的子树上继续进行,转①
其实现算法如下:
/** @description:递归查找二叉查找树是否存在否值*/BiTree SearchBST(BiTree T,TElemType key) { if(!T || T->data == key) return T; else if(T->data > key) return SearchBST(T->lchild,key); else return SearchBST(T->rchild,key);}
3.二叉排序树的插入
向二叉排序树中插入一个结点的过程:设待插入结点的关键码为key,为将其插入,先要在二叉排序树中进行查找,若查找成功,按二叉排序树定义,待插入结点已存在,不用插入;查找不成功时,则插入之。因此,新插入结点一定是作为叶子结点添加上去的。
如记录的关键码序列为:63,90,70,55,67,42,98,83,10,45,58,则构造一棵二叉排序树的过程如下:
其实现算法如下:
/** @description:在二叉排序树中插入不存在的元素*/Status InsertBST(BiTree *T,TElemType key) {BiTree p,s;//二叉排序中不存在要插入的节点值if(!Search_BST(*T,key,NULL,&p)) {s = (BiTree) malloc(sizeof(struct BiTNode));if(!s)exit(OVERFLOW);s->data = key;s->lchild = NULL;s->rchild = NULL;//如果为根节点if(!p)*T = s;//小于当前值的则作为左孩子else if(key < p->data)p->lchild = s;//大于当前值的则作为右孩子else p->rchild = s;return TRUE;}elsereturn FALSE;}/** @description:查找算法判断查找是否成功,主要是配合插入操作* @more:*p指向当前节点,f直线父亲节点,查找成功则返回TRUE,否则返回FALSE*/Status Search_BST(BiTree T,TElemType key,BiTree f,BiTree *p) {if(!T) {*p = f;return FALSE;}//查找成功else if(T->data == key) {*p = T;return TRUE;}//小于当前节点的值则往左子树找else if(T->data > key ) return Search_BST(T->lchild,key,T,p);//大于当前节点值则往右子树找else return Search_BST(T->rchild,key,T,p);}
4.二叉排序树的删除
从二叉排序树中删除一个结点之后,使其仍能保持二叉排序树的特性即可。设待删结点为*p(p 为指向待删结点的指针),其双亲结点为*f,以下分三种情况进行讨论。
1.*p 结点为叶结点,由于删去叶结点后不影响整棵树的特性,所以,只需将被删结点的双亲结点相应指针域改为空指针。如图9.6。
2.*p 结点只有右子树pr 或只有左子树pl,此时,只需将pr 或pl 替换*f 结点的*p 子树即可。如图9.7。
3.*p 结点既有左子树Pl 又有右子树Pr,可按中序遍历保持有序进行调整。
由于第三中情况比较坑爹,下面是一张第三种情况的图,但是我觉得这里最主要的就是将中序遍历的前序和后继调整好就行。
其实现算法如下:
/** @删除二叉排序树中某个节点*/Status DeleBST(BiTree *T,TElemType key) {if(!(*T))return FALSE;else {if((*T)->data == key)return Dele(T);else if((*T)->data > key)return DeleBST(&(*T)->lchild,key);else return DeleBST(&(*T)->rchild,key);}}/** @description:具体的删除操作* @more:1.如果左子树为空,则重新结它右子树;2.如果右子树为空,则重新结它的左子树3.如果左右子树都部位空,则用节点的前驱代替要删除的节点 且调整各项指针*/Status Dele(BiTree *p) {BiTree s,q;s = q = NULL;//如果左子树为空,则重新接为右子树if(! (*p)->lchild) {q = *p;*p = (*p)->rchild;free(q);}//如果右子树为空,则重新接为左子树else if(! (*p)->rchild) {q = *p;*p = (*p)->lchild;free(q);}//如果左右子树都不为空else {q = *p;s =(*p)->lchild;//向左转后,一直往右走直至尽头,为了找到p的前驱节点while(s->rchild) {q = s;s = s->rchild;}(*p)->data = s->data;//赋值//这里s节点为q的右孩子,s为p节点的前驱if(*p != q)q->rchild = s->lchild;//把s的左孩子结为q的右孩子else q->lchild = s->lchild;//重新结q的左孩子free(s);}return TRUE;}
5.二叉排序树的查找分析
二叉查找树中查找的运行时间与树T的高度成正比。因为有n个结点的树的高度小则为O(logn),大则为O(n).;对于有n个关键字元素的数据项,高度为h的二叉查找树T,空间复杂度为O(n);其中,查找元素,插入元素,删除元素的时间复杂度均为O(h);二叉排序树的查找过程与二分法相似,也是一个逐步缩小查找范围的过程。若查找成功,则走了一条从根结点到待查结点的路径;若失败,则是走了一条根结点到某个叶子结点的路径。因而,查找过程中和关键字的比较次数不超过树的深度。
由于含有n个结点的二叉排序树不唯一,因而有n个结点的二叉排序树的平均查找长度为树的形态有关;
最好的情况:二叉排序树和二叉判定树形态相同;
最坏的情况:二叉排序树为单支树,这时平均查找长度与顺序查找时相同;
就平均性能而言,二叉排序树上的查找与二分查找相差不大,且二叉排序树上的插入和删除结点十分方便,不用大量移动结点。
以上
最后附上完整源码地址:GitHub
- 数据结构之二叉排序树
- 数据结构之(二叉排序树)
- 数据结构学习之二叉排序树
- 数据结构之二叉排序树
- 数据结构之二叉排序树
- 数据结构之二叉排序树
- 数据结构之二叉排序树
- 数据结构之二叉排序树
- JAVA数据结构之二叉排序树
- 数据结构之二叉排序树
- JavaScript数据结构之 二叉排序树
- 数据结构之二叉排序树
- 数据结构之二叉排序树
- Python数据结构之二叉排序树
- 实用数据结构之二叉排序树小结
- 数据结构——查找之二叉排序树
- 数据结构实验之查找一:二叉排序树
- 数据结构实验之查找一:二叉排序树
- Windows下通过Telnet连接Linux主机
- 压缩感知中的lp球:p范数最优化为什么总会导致一个稀疏的解的原因
- JAVA中获取时间的两种方法
- Square Coins
- 生成设备对象
- 数据结构之二叉排序树
- String to Integer(atoi)
- 2-11. 两个有序链表序列的合并(15)
- Objective- C 编程 Block
- 数据结构之平衡二叉树
- 《数据结构》实验二:线性表的实验
- 九度OJ 1043 蔡勒公式
- deepin终于登录dr。com成功了,大笑三声
- Demo