算法笔记:二叉搜索树BST(未完待续)
来源:互联网 发布:linux zip 解压乱码 编辑:程序博客网 时间:2024/06/07 06:02
专题:二叉搜索树BST
一、定义
二叉搜索树(Binary Search Tree),也称有序二叉树或排序二叉树,是指一棵空树或者具有下列性质的二叉树:
1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
3. 任意节点的左、右子树也分别为二叉搜索树。
也就是说:设x是二叉搜索树中的一个节点。
如果y是x的左子树中的一个节点,则有y.key<x.key;
如果y是x的右子树中的一个节点,则有y.key>x.key。
二、结构与基本操作
1. 二叉搜索树具有很高的灵活性,对其优化可以生成平衡二叉树,红黑树等高效的查找和插入数据结构。
2. 基本操作:
(1)查找:查询是否包含某个数值
该查找方法也叫“树表查找”。类似二分查找,将待查找数值val和当前节点的值key比较:
若val=key,表示找到,返回该值或者找到的信息;
若val<key,则往左儿子节点走,在左子树中继续查找;
若val>key,则往右儿子节点走,在右子树中继续查找。
(2)插入:向二叉搜索树中插入某个节点
按照上述查找数值的方法试图查找这个数值的节点,就可以知道其对应的节点的所在位置,之后在那个位置插入新的节点即可。
【该过程可分解为”查找->插入”两步】
(3)删除:向二叉搜索树中删除某个节点
一般来说,需要根据下面几种情况分别进行处理:
① 需要删除的节点没有左儿子,那么就把右儿子提上去
② 需要删除的节点的左儿子没有右儿子,那么就把左儿子提上去
③ 以上两种情况都不满足的话,就把左儿子的子孙中最大的节点提到需要删除的节点上。
【该过程可分解为”查找->删除->调整”三步】
3. 一个特殊特性:对二叉搜索树进行中序遍历,可以得到节点值的有序序列。
三、复杂度分析
不论以上哪种操作,所花的时间都和树的高度成正比。因此,如果共有n个元素,则平均每次操作需要O(logn)的时间。
四、代码实现
#include <stdio.h>#include <stdlib.h>#define maxn 1010int n; //待插入BST的元素数int elem[maxn]; //待插入BST的元素typedef struct node //自定义二叉搜索树的节点{ int data; //键值 node *lchild; //左孩子 node *rchild; //右孩子} BST;void Init(BST *&b) //初始化BST(空树){ b=NULL;}BST *Insert(BST *&b,int x) //向BST中插入元素x,返回BST结构体的指针{ if(b==NULL) //当前节点为空时,创建新节点 { b=(BST *)malloc(sizeof(BST)); b->data=x; b->lchild=b->rchild=NULL; } else { if(x<b->data)//待插入节点比当前节点小,在左子树中插入 b->lchild=Insert(b->lchild,x); else //否则在右子树中插入 b->rchild=Insert(b->rchild,x); } return b;}int Find(BST *b,int x) //在BST中查找元素x{ if(b==NULL) //当前节点为空,表示未找到,返回0 return 0; else { if(b->data==x) //当前节点为待查找节点,表示找到,返回1 return 1; else if(x<b->data)//否则,在左子树中继续查找 return Find(b->lchild,x); else //在右子树中继续查找 return Find(b->rchild,x); }}BST *Remove(BST *p,int x) //在BST中删除元素x,返回BST结构体的指针{ BST *q,*r; //首先查找待删除节点x if(p==NULL) //当前节点为空,表示找不到,直接返回空 return NULL; else if(x<p->data) //待删除节点比当前节点小,在左子树中删除 p->lchild=Remove(p->lchild,x); else if(x>p->data) //待插入节点比当前节点大,在右子树中删除 p->rchild=Remove(p->rchild,x); //然后分别处理可能出现的三种情况 else if(p->lchild==NULL) //需要删除的节点没有左儿子 { q=p->rchild; //将右儿子提上去 free(p); return q; } else if(p->lchild->rchild==NULL) //需要删除的节点的左儿子没有右儿子 { q=p->lchild; //将左儿子提上去 q->rchild=p->rchild; free(p); return q; } else //其他情况 { for(q=p->lchild;q->rchild->rchild!=NULL;q=q->rchild); //将左儿子的子孙中最大的节点提到需要删除的节点上 r=q->rchild; q->rchild=r->lchild; r->lchild=p->lchild; r->rchild=p->rchild; free(p); return r; } return p;}void PreOrderBST(BST *b) //先序遍历BST{ if(b!=NULL) { printf("%d ",b->data); PreOrderBST(b->lchild); PreOrderBST(b->rchild); }}void InOrderBST(BST *b) //中序遍历BST{ if(b!=NULL) { InOrderBST(b->lchild); printf("%d ",b->data); InOrderBST(b->rchild); }}void PostOrderBST(BST *b) //后序遍历BST{ if(b!=NULL) { PostOrderBST(b->lchild); PostOrderBST(b->rchild); printf("%d ",b->data); }}void PrintOrder(BST *b) //打印BST先中后序遍历序列{ printf("PreOrderBST:"); PreOrderBST(b); printf("\n"); printf("InOrderBST:"); InOrderBST(b); printf("\n"); printf("PostOrderBST:"); PostOrderBST(b); printf("\n");}int main(){ int i; BST *b; Init(b); //初始化BST为空(很重要!) scanf("%d",&n); for(i=0;i<n;i++) //这里建立BST采用根据输入序列,逐个插入已初始化为空的树实现的 { scanf("%d",&elem[i]); Insert(b,elem[i]); } printf("Succeed!\n"); PrintOrder(b); printf("%d %d %d %d\n",Find(b,2),Find(b,6),Find(b,-3),Find(b,11)); Remove(b,7); printf("Succeed!\n"); PrintOrder(b); return 0;}/*测试数据104 2 1 0 3 5 9 7 6 8838 26 62 94 35 50 28 55*/
- 算法笔记:二叉搜索树BST(未完待续)
- 二叉搜索树(未完待续)
- 图解:二叉搜索树算法(BST)
- 学习笔记 二叉搜索树(BST)
- 剑指offer 二叉树(搜索二叉树插入,遍历)未完待续。。
- 算法笔记:贪心法(未完待续)
- 二叉树应用总结(未完待续)
- *BST(二叉搜索树)
- 二叉搜索树(BST)
- 算法-树(1)—BST(二叉搜索树)
- Java实现 二叉搜索树算法(BST)
- Java实现 二叉搜索树算法(BST)
- Java实现 二叉搜索树算法(BST)
- 算法导论—二叉搜索树(BST)
- BST二叉搜索树的查找算法
- BST 二叉搜索树 C++ 算法导论
- BST 二叉搜索树
- 二叉搜索树BST
- mySQL之数据类型
- 虚拟篇 03. Hyper-V 远程桌面捕获鼠标 ❀ Windows Server 2016
- 异步加载场景loading界面
- Vue2+VueRouter2+Webpack+Axios 构建项目实战2017重制版(十三)集成 UEditor 百度富文本编辑器
- elasticSearch 5.x.x版本 maven配置(一个坑)
- 算法笔记:二叉搜索树BST(未完待续)
- 坐标下降与梯度下降
- 利用Zipkin对Spring Cloud应用进行服务追踪分析
- Docker入门与实战详细笔记
- Spring事务传播机制和数据库隔离级别
- 进程和线程的区别
- UVA 208
- Git查看、删除、重命名远程分支和tag
- SVN主干和分支的合并