平衡二叉搜索树

平衡二叉树:每个结点的左右子树高度差不超过1,左右子树均为平衡二叉树
搜索二叉树:左结点 < 根结点 <右结点
平衡二叉搜索树则是优化后的搜索二叉树,使得查找的效率提升,但是在添加数据时,需要进行复杂的判断,所以一般使用在查找频繁修改很少的存储结构中。

平衡二叉树的建立

整个建立过程分为三大部分:
①插入新的结点
②判断插入结点后树是否平衡,并找到不平衡的点
③若不平衡,判断旋转方向,进行调整

插入新的结点

这一个步骤较为容易实现,按照搜索二叉树的性质:将数据与结点数据进行比较,小于走左树,大于走右树,直到走到叶子结点,建立新结点,将数据进行插入。

判断新树的平衡,并找到不平衡的点

不平衡的点即需要进行旋转调整的点,这时就有一个问题:如果根结点和子树同时变为不平衡状态,那么应该调整哪个点?
我的想法:由于整个树的添加和变化是一个动态规划的过程,每一步的变动都会影响下一步。当新结点的加入只有两种情况:
①根和子树都不平衡时,先调整子树使其到达平衡状态,此时根也会随着子树变得平衡。
②根不平衡,直接调整根。

关于不平衡点的定位:不平衡的点只出现在添加数据时所途径的点,所以使用栈将其进行存储,再出栈进行判断。

判断旋转方向,进行调整

树的旋转有四种,每一种方式都针对着不同的非平衡状态。所以,需判断以不平衡结点为根的树的结构。
其实,对于每一种旋转(RR、LL、RL、LR)都指的是从根结点到破坏结点是所走结点的方向(R指左子树,L指右子树),而且只需判断前两步即可。
此时,判断方向也需要借助于栈中存储的途径结点:在回溯判断是否平衡时,记录路径,用以判断旋转方向。

实际建立过程

插入结点
/*** 添加新结点* @param data  数据* @param sBalance  栈* @return 新结点*/private TreeNode addNewData(String data,StackBalance sBalance){  //遍历树,找到位置添加TreeNode moveNode = this.rootNode;int numData = Integer.parseInt(data);while(moveNode != null) {sBalance.pop(moveNode);            //存储遍历结点的父结点if(numData < Integer.parseInt(moveNode.getData())) {moveNode = moveNode.getLeChild();}else {moveNode = moveNode.getRiChild();}   }TreeNode midNode = new TreeNode();midNode.setData(data);//判断为左孩子还是右孩子TreeNode parNode = sBalance.seekTop();if(numData < Integer.parseInt(parNode.getData())){parNode.setLeChild(midNode);}else {parNode.setRiChild(midNode);} return midNode;}
判断是否平衡

用到了我之前写的平衡函数:BalanceJudge.optiBalance(parNode, depth)

/*** 是否平衡,不平衡并返回该结点,平衡返回null* @param sBalance 栈* @param midNode 新加结点* @param track 路径* @return 不平衡结点*/private TreeNode ifBalance(StackBalance sBalance, TreeNode midNode,char track[]) {//判断树是否平衡,不平衡进行旋转//依靠栈中元素,逐步出栈判断父结点的平衡状态int depth[] = new int[1];TreeNode sonNode = midNode;TreeNode parNode = sBalance.push();while(BalanceJudge.optiBalance(parNode, depth)) {//当当前结点平衡时,记录到添加结点的路径if(parNode.getLeChild() == sonNode) {track[1] = track[0];track[0] = 'l';}else {track[1] = track[0];track[0] = 'r';}if(!sBalance.ifEmpty()) {sonNode = parNode;parNode = sBalance.push();}else {break;}    }//不平衡记录if(BalanceJudge.optiBalance(parNode, depth)) {if(parNode.getLeChild() == sonNode) {track[1] = track[0];track[0] = 'l';}else {track[1] = track[0];track[0] = 'r';}return parNode; } return null;}
对不平衡结点进行旋转

用到了我之前写的旋转函数:BalanceSpin.LLSpin(unBalance)、BalanceSpin.LLSpin(unBalance)、BalanceSpin.LLSpin(unBalance)、BalanceSpin.LLSpin(unBalance)

/*** 对不平衡结点进行旋转* @param sBalance 栈* @param unBalance 不平衡结点* @param track 路径*/private void treeSpin(StackBalance sBalance,TreeNode unBalance,char track[]) {  TreeNode afSpinNode = null; //记录旋转后不平衡子树的根结点if(track[0] == 'l' && track[1] == 'l') {afSpinNode = BalanceSpin.LLSpin(unBalance);System.out.println(" LL型旋转");}else if(track[0] == 'r' && track[1] == 'r') {afSpinNode = BalanceSpin.RRSpin(unBalance);System.out.println(" RR型旋转");}else if(track[0] == 'l' && track[1] == 'r') {afSpinNode = BalanceSpin.LRSpin(unBalance);System.out.println(" LR型旋转");}else if(track[0] == 'r' && track[1] == 'l') {afSpinNode = BalanceSpin.RLSpin(unBalance);System.out.println(" RL型旋转");}//判断是否为根结点,若不是则要更改父结点处的引用if(unBalance != this.rootNode) {TreeNode faNode = sBalance.push(); //取出父结点//判断左右孩子if(faNode.getLeChild() == unBalance) {faNode.setLeChild(afSpinNode);}else {faNode.setRiChild(afSpinNode);}}else {this.rootNode = afSpinNode;}}

PS:我此处没设置,数据相等时怎么办,可以在插入数据时添加等号进行判断

主函数(将之前几个函数统一起来)
/*** 根据文件内容建立一个平衡二叉树* @param file 文件名* @return   根结点*/public TreeNode file2BalanceTree(String file) {try {BufferedReader bReader = new BufferedReader(new FileReader(file));StackBalance sBalance = new StackBalance();String data = bReader.readLine();//根结点if(this.rootNode == null) {this.rootNode = new TreeNode();this.rootNode.setData(data);  }  while((data = bReader.readLine()) != null) {//添加新结点TreeNode midNode = addNewData(data, sBalance);    //判断平衡char[] track = new char[2];  //记录两步用以判断旋转方向TreeNode unBalance = ifBalance(sBalance, midNode, track);//当前结点不平衡,旋转   if(unBalance != null) { System.out.print("插入数据:"+midNode.getData()+"时,导致结点:");System.out.print(unBalance.getData()+"不平衡");treeSpin(sBalance, unBalance, track);   }     }     bReader.close();} catch (Exception e) {e.printStackTrace();}return this.rootNode;}
测试结果

①单旋

②双旋

平衡二叉搜索树的创建相关推荐

  1. 最适合新手看的平衡二叉搜索树(BBST)的创建,包含详细过程,一看就会(C++版)

    写在前面:本人大二小白,本篇文章是我第一次写博客,用来记录我的学习过程,我想将我在学习中遇到的各种的问题和困难写下来,希望大家能够不要犯同样的错误.我会尽可能的详细的把每一个步骤都解释清楚,那么废话不 ...

  2. 看动画学算法之:平衡二叉搜索树AVL Tree

    简介 平衡二叉搜索树是一种特殊的二叉搜索树.为什么会有平衡二叉搜索树呢? 考虑一下二叉搜索树的特殊情况,如果一个二叉搜索树所有的节点都是右节点,那么这个二叉搜索树将会退化成为链表.从而导致搜索的时间复 ...

  3. 牛客题霸 [将升序数组转化为平衡二叉搜索树]C++题解/答案

    牛客题霸 [将升序数组转化为平衡二叉搜索树]C++题解/答案 题目描述 给出一个升序排序的数组,将其转化为平衡二叉搜索树(BST). 题解: 二叉搜索树的定义: 二叉搜索树或者是一棵空树,或者是具有下 ...

  4. 程序员面试金典 - 面试题 17.11. 单词距离(multimap平衡二叉搜索树)

    1. 题目 有个内含单词的超大文本文件,给定任意两个单词,找出在这个文件中这两个单词的最短距离(相隔单词数). 如果寻找过程在这个文件中会重复多次,而每次寻找的单词不同,你能对此优化吗? 示例: 输入 ...

  5. 红黑树 平衡二叉搜索树_红黑树:自我平衡的二叉搜索树,并举例说明

    红黑树 平衡二叉搜索树 什么是红黑树? (What is a Red-Black Tree?) Red-Black Tree is a type of self-balancing Binary Se ...

  6. 《恋上数据结构第1季》平衡二叉搜索树、AVL树

    AVL树 二叉搜索树缺点分析 改进二叉搜索树 平衡(Balance) 理想平衡 如何改进二叉搜索树? 平衡二叉搜索树(Balanced Binary Search Tree) AVL树 BST 对比 ...

  7. 数据结构与算法-平衡二叉搜索树

    平衡二叉搜索树 1.自平衡的二叉搜索树 2.平衡 (1)空树平衡 (2)非空树平衡 左右子树平衡 左右子树高度差绝对值 <= 1 3.平衡因子 左右子树的高度差的衡量值 -1 0 1 (一)平衡 ...

  8. 二叉搜索树(平衡二叉搜索树)

    二叉搜索树 1.验证是否为二叉搜索树 中序遍历看是否为递增序列 2.平衡二叉搜索树 将升序序列转为二叉平衡搜索树 /***树的结构体* Definition for a binary tree nod ...

  9. VC++2012编程演练数据结构《9》平衡二叉搜索树

    平衡二叉搜索树 任何结点的左子树和右子树高度最多相差1的二叉搜索树. (1)AVL树的插入算法 a. 插入结点之后仍然是AVL树,则不调整: b. 插入结点之后不再满足AVL树条件,则进行调整,根据导 ...

最新文章

  1. LeetCode 421. Maximum XOR of Two Numbers in an Array--Python解法
  2. 线程执行者(十一)执行者分离任务的启动和结果的处理
  3. 基于Vue+Nodejs实现宿舍管理系统
  4. Mybatis中的jdbcType的作用
  5. JavaScript中十个一步拷贝数组的方法
  6. IOS5开发-http get/post调用mvc4 webapi互操作(图片上传)
  7. [译] 学习 Spring Security(四):使用邮箱激活新账户
  8. 构建多基因的系统发育树
  9. 嗖嗖移动业务大厅(源码下载+注释全 值得收藏)
  10. 怎么修改服务器上传图片,更换服务器后,为什么百度编辑器无法上传图片了
  11. python overflowerror_Python中的OverflowError:(34,'结果太大')
  12. 【AUTOSAR-COM】-10.3-接收的IPDU Callout(Com_RxIpduCallout)的使用小结
  13. 入手python难不难_Python难不难?容易学吗?
  14. 2021 新款手机,免费送!
  15. python tk窗口 选择 销毁_Python tkinter - 删除其他窗口 - 已调用tk.withdraw()
  16. linux系统忘记登录密码怎么办
  17. STM32配置单片机系统时钟(转)
  18. @2021届毕业,各种招聘平台大集合!
  19. (附源码)计算机毕业设计SSM智慧校园防疫管理平台
  20. 新型冠状病毒可能就在身边,如何进行自我防护?

热门文章

  1. Hibernate教程
  2. 基于Spring安全角色的访问授权示例
  3. @vail 判断某字段在范围内_怎么判断一台二次元影像测量仪的可靠性?
  4. 隐马尔可夫(HMM)/感知机/条件随机场(CRF)----词性标注
  5. springboot logback 日志配置
  6. mac应用开发入门笔记
  7. 119_Power Pivot 长尾明细显示为【其他】
  8. vscode调试redis源码
  9. Python编程 | 新手必会的 9 个 Python 技巧
  10. jQuery基础部分笔记