二叉搜索树(BST)和平衡二叉树(AVL树)的概念与理解
树的典型应用
二叉搜索树
静态查找:所查找集合的元素时不动的,在一个集合上主要做的便是find操作,而没有delete一个映射的操作
方法:二分查找,将要查找的数据事先的有序化
动态查找:所查找对象会发生变化,经常要发生插入,删除操作
书上的任意的一个结点他的值比左子树的值都要来的大,比右子树的值都要小,查找过程便成为了对当前结点的判断。
二叉搜索树(BST)—二叉排序树/二叉查找树
- 一颗二叉树,可以为空,如果不为空需满足
- 非空左子树的所有键值小于其根结点的键值
- 非空右子树的所有键值大于其根结点的键值
- 左,右子树都是二叉搜索树
操作函数
- Position Find(elementtype x,bintree bst):从二叉搜索树BST中查找元素X,返回其所在结点的地址
- Position Findmin(bintree bst):从二叉搜索树BST中查找并返回最小元素所在结点的地址
- Position Findmax(bintree bst):从二叉搜索树BST中查找并返回最大元素所在结点的地址
- bintree insert(elementtype x,bintree bst),插入
- bintree delete(elementtype x,bintree bst),删除
查找操作
- 查找从根结点开始,如果树为空,返回NULL;
- 若搜索树非空,则根结点关键字和X进行比较,并进行不同处理
- 若X小于根结点键值,只需在左子树中继续搜索
- 若X大于根节点的键值,在右子树中进行继续搜索
- 若两者比较结果是相等,搜索完成,返回指向此结点的指针
//尾递归
bintree find(ELementtype x, bintree bst)
{if (!bst)return NULL;//查找从根结点开始,如果树为空,返回NULL;if (x > bst->data){return find(x, bst->right);//若X大于根节点的键值,在右子树中进行继续搜索}if (x < bst->data){return find(x, bst->left);//若X小于根结点键值,只需在左子树中继续搜索}elsereturn bst;//若两者比较结果是相等,搜索完成,返回指向此结点的指针
}
由于非递归函数的执行效率高,可将尾递归函数改为迭代函数
//递归实现版
bintree iterfind(ELementtype x, bintree bst)
{while (bst){if (x > bst->data){bst=bst->right;//若X大于根节点的键值,在右子树中进行继续搜索}if (x < bst->data){bst = bst->left;//若X小于根结点键值,只需在左子树中继续搜索}elsereturn bst;//若两者比较结果是相等,搜索完成,返回指向此结点的指针}return NULL;//查找从根结点开始,如果树为空,返回NULL;
}
查找的效率决定于树的高度
查找最大和最小元素
- 最大元素一定是在树的最右分支的端结点上
- 最小元素一定是在树的最左分支的端结点上
//递归
bintree findmin(bintree bst)
{if (!bst)return NULL;else if (!bst->left)return bst;//一直查找有没有左节点,左结点如果没有代表就是最小结点所在的位置elsereturn findmin(bst->left);
}//循环
bintree findmax(bintree bst)
{if (bst){while (bst->right){bst = bst->right;}}return bst;
}
二叉搜索树插入
分析:关键是要找到元素应该插入的位置
bintree insert(ELementtype x, bintree bst)
{//若原树为空,生成并返回一个结点的二叉搜索树if (!bst){bst =(bintree)malloc(sizeof(struct treenode));bst->data = x;bst->left = bst->right = NULL;}else {//开始查找要插入元素的位置if (x < bst->data){bst->left = insert(x, bst->left);}else if (x > bst->data){bst->right = insert(x, bst->right);}//当找到了便将x赋给新建的空结点中}return bst;
}
二叉搜索树的删除
- 要删除的是叶结点,直接删除,再修改其父结点指针,置为NULL
- 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除结点的孩子结点
- 要删除的结点有左右两颗子树,用另一结点替代被删除结点,右子树的最小元素或则左子树的最大元素,原因,无论左子树的最小值或者右子树的最小值一定不会有两个结点
bintree deletetree(ELementtype x, bintree bst)
{bintree tmp;if (!bst){cout << "we can`t finf the num" << endl;}else if (x > bst->data){bst->right = deletetree(x, bst->right);//左子树递归删除}else if (x < bst->data){bst->left = deletetree(x, bst->left);//右子树递归删除}else{if (bst->left && bst->right)//左右两边都不空{tmp = findmin(bst->right);//找到右子树的最小值进行替代bst->data = tmp->data;bst->right = deletetree(bst->data, bst->right);}else{//被删除结点有一个或无子结点tmp = bst;if (!bst->left)//有右子树或无子结点{bst = bst->right;}else if (!bst->right)//有左子树或无子结点{bst = bst->right;}free(tmp);}}return bst;
}
平衡二叉树
搜索树结点的不同插入次序,会导致不同的深度和平均查找长度ASL不同
左右两边结点数差不多,左右两边的高度差不多
- 平衡因子(BF),BF(T)=hL-hR
- hL,hR分别是T的左右子树的高度
平衡二叉树(AVL树)
任一结点的左右子树高度差的绝对值不超过1,即|BF(T)|<=1
高度为h的最小结点数=高度为h-1时最小结点数+高度为h-2时最小结点数+1
类似于斐波那契数列,nh=f(h+2)-1
给定结点数为n的AVL树的最大高度为O(log2(n))
平衡二叉树的调整
右旋
无论如何调整,都必须保证搜索树的框架能够成立
RR旋转,RR插入,右单旋
LL旋转,LL插入,左单旋
LR旋转,LR插入,左右旋转
RL旋转,RL插入
怎么判别:便是看插入结点把谁给破坏了
小白专场
题目:判断是否为同一颗二叉搜索树
给定一个插入序列可以唯一确定一颗二叉搜索树,然而一颗给定的二叉搜索树可以由多种不同的插入序列得到
对于输入的各种个插入序列,需要判断他们是否可以生成一样的二叉搜索树
求解思路
- 分别建两颗搜索树的判别方法
- 不建树的判别方法
- 建一颗树,再判别其他序列是否与该树一致
- 搜索树表示
- 建搜索树T
- 判别一序列是否与搜索树T一致
程序框架搭建
主函数
- 读取N和L
- 根据第一行序列建树T
- 依据树T分别判别后面的L个序列是否能与T形成同一搜索树并输出结果
- 主要建立两个函数,读入数据建立搜索树T,判别序列是否与T构成一样的搜索树
判别方法
如何判别序列与树t是否一致
方法:再树t中顺序搜索序列中的每个数
- 若每次搜索所经过的结点再前面均出现过,则一致
- 否则(某次搜索中遇到前面你未出现过的结点),则不一致
#include <stdio.h>
#include <stdlib.h>
#include<iostream>using namespace std;typedef struct Treenode* tree;//建立搜索树
struct Treenode
{int v;tree left, right;int flag;//用来判别一个序列是不是与树一致,作为结点有无被访问过的标记
};int main()
{int N,L,i;tree T;cin >> N;while (N){cin >> L;T = maketree(N);for (i = 0; i < L; i++){if (judge(T,N)){cout << "yes" << endl;}else{cout << "no" << endl;}resetT(T);//清除T中的标记flag}freetree(T);cin >> N;}return 0;}tree maketree(int n)
{tree t;int i, v;cin >> v;t = newnode(v);for (i = 1; i < n; i++){cin >> v;t = insert(t, v);}return t;
}tree newnode(int v)
{tree t = (tree)malloc(sizeof(struct Treenode));t->v = v;t->left = t->right = NULL;t->flag = 0;return t;
}tree insert(tree t, int v)
{if (!t)t = newnode(v);else {if (v > t->v){t->right = insert(t->right, v);}elset->left = insert(t->left, v);}return t;
}int check(tree t, int v)
{if (t->flag){if (v < t->v)return check(t->left, v);else if (v > t->v)return check(t->right, v);elsereturn 0;}else{if (v == t->v){t->flag = 1;return 1;}elsereturn 0;}
}//当发现序列中的某个数与T不一致时,必须把该序列后面的数全部都读完
int judge(tree t, int n)
{int i, v,flag = 0;//flag=0,代表目前还是一致的,1代表已经不一致了cin >> v;if (v != t->v)flag = 1;elset->flag = 1;for (i = 1; i < n; i++){cin >> v;if (!flag && !check(t, v))flag = 1;}if (flag)return 0;elsereturn 0;
}void resetT(tree t)//清除t中的每个结点的flag标记
{if (t->left)resetT(t->left);if (t->right)resetT(t->right);t->flag = 0;
}void freetree(tree t)//释放结点
{if (t->left)freetree(t->left);if (t->right)freetree(t->right);free(t);
}
二叉搜索树(BST)和平衡二叉树(AVL树)的概念与理解相关推荐
- 第七章 二叉搜索树 (d2)AVL树:插入
转载于:https://www.cnblogs.com/ZHONGZHENHUA/p/10246808.html
- 真c++ 从二叉树到红黑树(3)之二叉搜索树BST
此文章为从二叉树到红黑树系列文章的第三节,主要介绍介绍二叉搜索树BST,为AVL和RedBlack打下基础 文章目录 一.前面文章链接~(点击右边波浪线可以返回目录) 二.二叉搜索树BST的定义~ ...
- 五.树,二叉树,二叉搜索树(BST)和自平衡二叉搜索树(AVL)
1.树 树是一种数据结构 比如:目录结构 树是一种可以递归定义的数据结构 树是由n个节点组成的集合: 如果 n=0, 那这是一颗空树 如果 n>0, 那存在1个节点作为树的根节点,其他节点可以分 ...
- 二叉搜索树BST红黑树
二叉搜索树基础知识 提起红黑树咱们肯定要先说说这个二叉搜索树(BST) 二叉搜索树又叫二叉查找树,二叉排序树:它具有以下特点: 如果它的左子树不为空,则左子树上结点的值都小于根结点. 如果它的右子树不 ...
- 二叉搜索树BST的学习
文章目录 二叉搜索树BST 什么是BST? 用BST做什么? 一.BST的特性 BST的特性是什么? 1.[230. 二叉搜索树中第K小的元素](https://leetcode.cn/problem ...
- 二叉搜索树(BST的理论剖析+代码实现)
二叉搜索树(BST树) 文章目录 二叉搜索树(BST树) 1.二叉搜索树的概念 2.二叉搜索树的结构定义 2.1 二叉搜索树结点模板的定义 2.2 二叉搜索树类模板的定义 3.二叉搜索树的效率 4.二 ...
- 看动画学算法之:二叉搜索树BST
文章目录 简介 BST的基本性质 BST的构建 BST的搜索 BST的插入 BST的删除 看动画学算法之:二叉搜索树BST 简介 树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的 ...
- 二叉搜索树 (BST)
二叉搜索树 (BST : Binary Search Tree) 又名 二叉查找树 或 二叉排序树. 二叉搜索树: 左孩子的值 一定小于或等于 父结点的值 二叉搜索树: 右孩子的值 一定大于或等于 父 ...
- 二叉搜索树(BST)详解
数据结构:二叉搜索树(BST) 今天咱们来聊聊二叉搜索树,先从字面上来理解,二叉,指的是有两个分支,左子树和右子树:搜索树,啥意思呢,搜索,是不是就是之前学过dfs和bfs那边学过,对啊,dfs就是深 ...
- 【数据结构与算法】3.二叉搜索树(BST)、c++代码
二叉搜索树(BST).c++代码 参考 https://blog.csdn.net/c_living/article/details/81021510
最新文章
- 给django视图类添加装饰器
- 华为交换机SSH登录失败原因
- no module named sklearn
- Lesson 5.分类模型决策边界与模型评估指标
- Linq to sql 实现多条件的动态查询(方法一)
- DNS、IP地址、子网掩码和网关
- BeanUtils.copyProperties() 用法
- 苹果手机透明桌面_原来苹果手机辨别真假很容易!查看桌面1个图标,就能轻松分辨...
- 苹果cms V10模板 仿特视网自适应模板
- 基于highcharts+easui+java生成时趋图
- Linux服务器上安装node.js
- 拓端tecdat|使用Python和Keras进行主成分分析、神经网络构建图像重建
- y电容如何选型_到底什么是安规电容?有什么作用?一文彻底请明白
- 关闭微软拼音输入法自带的emoji表情包
- 微信抽奖小程序怎么做怎么弄?微信抽奖小程序制作方法详细介绍
- 编程不是一种知识,而是一门手艺。
- 利用python拼接图片代码_Python实现图片拼接的代码
- [转载]看我花式绕过校园网计费认证
- impala添加kerberos认证
- web页面:窗口切换
热门文章
- 微信公众平台开发之导入 jar 包
- 微服务大战:春季启动大战。 芭蕾舞女演员
- 【笔记整理】软考-软件设计师
- 通过Python的pyttsx3库将文字转为音频
- Android系统_MTK_android11_集成openssh
- 【经验分享】关于RT-Thread studio gitee源下载软件包失败以及git拉取Gitee仓库报错
- 【C++】C++ 中的 IO 流
- blog开通,幸甚! ^_^
- 大气科学计算机,这所高校大气科学学科世界一流,被誉为“气象人才的摇篮”...
- 华为用一己之力,撬动了整个未来!