平衡二叉查找树(AVL)的插入
来源:互联网 发布:清朗网络 青年力量海报 编辑:程序博客网 时间:2024/05/16 16:14
平衡二叉查找树的概念就不多介绍了,这边主要说明一下如何进行插入操作
在平衡二叉树中插入结点与二叉查找树最大的不同在于要随时保证插入后整棵二叉树是平衡的。那么调整不平衡树的基本方法就是: 旋转 。 下面我们归纳一下平衡旋转的4种情况
1) 绕某元素左旋转 LL(右子树出现右不平衡)
分析一下:在插入数据100之前,左图中的 ST树只有80节点的平衡因子是-1(左高-右高),但整棵树还是平衡的。加入100之后,80节点的平衡因子就成为了-2,此时平衡被破坏。需要左旋转成右图。
当树中节点X的右孩子的右孩子上插入新元素,且平衡因子从-1变成-2后,就需要绕节点X进行左旋转。
2) 绕某元素右旋转 RR(左子树出现左不平衡)
当树中节点X的左孩子的左孩子上插入新元素,且平衡因子从1变成2后,就需要绕节点X进行右旋转。
3) 绕某元素的左子节点左旋转,接着再绕该元素自己右旋转。 此情况下就是左旋与右旋 的结合,具体操作时可以分解成这两种操作,只是围绕点不一样而已。LR(左子树出现右不平衡)
当树中节点X的左孩子的右孩子上插入新元素,且平衡因子从1变成2后,就需要先绕X的左子节点Y左旋转,接着再绕X右旋转
4) 绕某元素的右子节点右旋转,接着再绕该元素自己左旋转。 此情况下就是 右旋与左旋 的结合,具体操作时可以分解 成这两种操作,只是围绕点不一样而已 。RL(右子树左不平衡)
当树中节点X的右孩子的左孩子上插入新元素,且平衡因子从-1变成-2后,就需要 先绕X的右子节点Y右旋转,接着再绕X左旋转
附上这几种操作的java版本的代码,代码自己用不同的用例测过,如果有什么地方没有考虑到,欢迎指正^0^
import java.util.ArrayList;import java.util.List;public class AVL { class TreeNode{ int value; int bf; TreeNode left,right; TreeNode(int v){ value = v; bf = 0; } } public TreeNode buildTree(int[] nums){ if(nums.length == 0) return null; TreeNode PRoot = new TreeNode(0); TreeNode root = new TreeNode(nums[0]); //为了能让后面可以改变root的地址而设 PRoot.left = root; for(int i = 1; i < nums.length ; i++){ insertTree(nums[i],PRoot); } return root; } public void insertTree(int num,TreeNode PRroot){ if(PRroot.left == null) return; TreeNode A=PRroot.left , B=PRroot.left ; TreeNode insertNode = new TreeNode(num); TreeNode temp = PRroot.left ; TreeNode AFather = null,tempFather = null; while(temp != null){ //找到从下到上最近的可能出现不平衡的节点 if(temp.bf != 0){ A = temp; AFather = tempFather; } tempFather = temp; if(num < temp.value) temp = temp.left; else temp = temp.right; } //插入孩子 if(num > tempFather.value) tempFather.right = insertNode; else tempFather.left = insertNode; adjustBalance(A,AFather,insertNode,PRroot);// printTree(PRroot); } public TreeNode updateBF(TreeNode insert,TreeNode node){ if(insert.value < node.value){ node.bf +=1; return node.left; } else { node.bf -= 1; return node.right; } } public void adjustBalance(TreeNode A,TreeNode AFather,TreeNode insert,TreeNode PRoot){ //确定B节点,修改A的bf TreeNode B = updateBF(insert,A);; //B不是插入点则也需要更新B的bf System.out.println("B.value= " + B.value); //在原来都平衡的一边加上一个值,A就会是root,所以要修改从B到插入节点之间的bf值 TreeNode temp = B; while(temp.value != insert.value){ updateBF(insert,temp); if(insert.value < temp.value) temp = temp.left; else temp = temp.right; } //LL if(A.bf == 2 && B.bf == 1){ A.left = B.right; B.right = A; A.bf = 0; B.bf = 0; updateChild(AFather,A,B,PRoot); } //RR else if(A.bf == -2 && B.bf == -1){ A.right = B.left; B.left = A; A.bf = 0; B.bf = 0; updateChild(AFather,A,B,PRoot); } //LR else if(A.bf == 2 && B.bf == -1){ TreeNode C = B.right; //先往左转成LL B.right = C.left; C.left = B; //LL A.left = C.right; C.right = A; //插入的点如果比C大最后会落在A的左边,比C小会落在B的右边 //A的右边 和B的左边一定有元素 if(insert.value > C.value){ A.bf = 0; B.bf = -1; C.bf = 0; } else if(insert.value < C.value) { A.bf = 1; B.bf = 0; C.bf = 0; } //插入点就是C的话 else{ A.bf = 0; B.bf = 0; } updateChild(AFather,A,C,PRoot); } //RL else if(A.bf == -2 && B.bf == 1){ TreeNode C = B.left; //先转成RR B.left = C.right; C.right = B; //RR A.right= C.left; C.left = A; //插入的点如果比C大最后会落在B的左边,比C小会落在A的右边 //因为B右边和A的左边一定会有元素 if(insert.value > C.value){ B.bf = 0; A.bf = 1; C.bf = 0; } else if(insert.value < C.value){ A.bf = 0; B.bf = -1; C.bf = 0; } //C就是要插入的元素 else{ A.bf = 0; B.bf = 0; } updateChild(AFather,A,C,PRoot); } } public void updateChild(TreeNode father,TreeNode originChild,TreeNode newChild,TreeNode PRoot){ if(father == null) PRoot.left = newChild; else if(originChild == father.left) father.left = newChild; else father.right = newChild; } public void printTree(TreeNode tree){ if(tree.left == null) return; List<TreeNode> nodes = new ArrayList<TreeNode>(); nodes.add(tree.left); printNode(nodes,"value"); System.out.println("***************"); printNode(nodes,"bf"); System.out.println("#################"); } public void printNode(List<TreeNode> nodes,String type){ if(nodes.size() == 0) return; List<TreeNode> childs = new ArrayList<TreeNode>(); for(TreeNode node:nodes){ if(type.equals("value")) System.out.print(node.value + " "); else System.out.print(node.bf + " "); if(node.left != null) childs.add(node.left); if(node.right != null) childs.add(node.right); } System.out.println(); printNode(childs,type); } public static void main(String[] args){ int[] nums={10,20,29,24,12,53,45,90,100,290,28}; AVL avl = new AVL(); TreeNode tree = avl.buildTree(nums); avl.printTree(tree); }}
- 平衡二叉查找树(AVL)的查找、插入、删除
- 平衡二叉查找树(AVL)的查找,插入,删除
- 平衡二叉查找树(AVL)的插入
- 平衡二叉树(AVL树)的查找,插入和删除
- 平衡二叉树(AVL)的插入操作
- 平衡二叉查找树 AVL 的实现
- AVL树(平衡二叉查找树)
- AVL树(平衡二叉查找树)
- AVL树(平衡二叉查找树)
- 平衡二叉查找树(AVL)
- 平衡二叉树(AVL)的创建、插入、删除
- 平衡二叉树(AVL树)的创建,查找
- 平衡二叉查找树[AVL]
- AVL--平衡二叉查找树
- 平衡二叉查找树 [AVL]
- 平衡二叉查找树 [AVL]
- 平衡二叉查找树 [AVL]
- AVL二叉平衡查找树
- Android Activity 跳转以及两者间传值的问题
- java中使用String的replace方法替换html模板保存文件
- 解决ios下html5的ifream页面无法滑动的问题
- 激光雷达学习笔记(五)圆弧
- static关键字
- 平衡二叉查找树(AVL)的插入
- 数据结构学习总结
- 手机号定位骗子揭秘,说精准的都是骗子(原创)
- 数据库连接池c3p0和dbcp和tomcat-dbcp
- 关于Scrapy 自定义Spider Middleware中遇到的坑
- <img src 引入base64格式数据 显示图片 >
- 条件阻塞Condition的应用
- Nginx配置proxy_pass转发的/路径问题
- applicationContext.xml配置hibernate 自动生成表失败