1. package com.tomsnail.data.tree;
  2. /**
  3. * AVL二叉平衡树
  4. * @author tomsnail
  5. * @date 2015年3月30日 下午4:35:50
  6. */
  7. public class AVLTree {
  8.  
  9. /**
  10. * 根节点
  11. * @author tomsnail
  12. * @date 2015年3月30日 下午4:36:54
  13. */
  14. private AVLNode rootNode;
  15.  
  16. private String bulidType = "";
  17.  
  18. /**
  19. * 增加一个节点
  20. * @author tomsnail
  21. * @date 2015年3月30日 下午4:36:08
  22. */
  23. public void add(int value){
  24. AVLNode subNode = null;
  25. if(rootNode==null){
  26. subNode = new AVLNode(value);
  27. rootNode = subNode;
  28. }else{
  29. subNode = addNode(rootNode,value);
  30. }
  31. reBuild(subNode);
  32.  
  33. }
  34.  
  35. private AVLNode addNode(AVLNode node,int value){
  36. AVLNode subNode = null;
  37. if(node.getValue()>value){
  38. if(node.getLeftNode()==null){
  39. subNode = new AVLNode(value);
  40. node.setLeftNode(subNode);
  41. }else{
  42. subNode = addNode(node.getLeftNode(), value);
  43. }
  44. }
  45. if(node.getValue()<value){
  46. if(node.getRightNode()==null){
  47. subNode = new AVLNode(value);
  48. node.setRightNode(subNode);
  49. }else{
  50. subNode = addNode(node.getRightNode(),value);
  51. }
  52. }
  53. return subNode;
  54. }
  55. /**
  56. * 重平衡树
  57. * @author tomsnail
  58. * @date 2015年3月30日 下午5:42:00
  59. */
  60. private void reBuild(AVLNode node){
  61. if(node!=null){
  62. AVLNode tempRootNode = findTempRootNode(node);
  63. if(tempRootNode!=null){
  64. if(bulidType.equals("ll")){
  65. Lrotate(node,tempRootNode);
  66. }else if(bulidType.equals("rr")){
  67. Rrotate(node,tempRootNode);
  68. }else if(bulidType.equals("lr")){
  69. Rrotate(node,tempRootNode.getLeftNode());
  70. Lrotate(node,tempRootNode);
  71. }else if(bulidType.equals("rl")){
  72. Lrotate(node,tempRootNode.getRightNode());
  73. Rrotate(node,tempRootNode);
  74. }
  75. reBuild(tempRootNode);
  76. }
  77. }
  78. }
  79. /**
  80. * 右旋
  81. * @author tomsnail
  82. * @date 2015年3月30日 下午9:23:28
  83. */
  84. private void Rrotate(AVLNode node,AVLNode tempRootNode){
  85. AVLNode rotateNode = tempRootNode.getRightNode();//旋转节点
  86. AVLNode rootNode = tempRootNode.getRootNode();//主根节点
  87. String type = "";
  88. if(rootNode!=null){
  89. if(rootNode.getLeftNode()==tempRootNode){
  90. type="l";
  91. }else{
  92. type="r";
  93. }
  94. }
  95. AVLNode adjustNode = rotateNode.getLeftNode();//调整节点
  96. rotateNode.setLeftNode(tempRootNode);
  97. tempRootNode.setRightNode(null);
  98. if(adjustNode!=null){
  99. tempRootNode.setRightNode(adjustNode);
  100. }
  101. if(rootNode==null){
  102. rotateNode.setRootNode(null);
  103. this.rootNode = rotateNode;
  104. }
  105. if(type.equals("r")){
  106. rootNode.setRightNode(rotateNode);
  107. }else if(type.equals("l")){
  108. rootNode.setLeftNode(rotateNode);
  109. }
  110. }
  111. /**
  112. * 左旋
  113. * @author tomsnail
  114. * @date 2015年3月30日 下午9:23:28
  115. */
  116. private void Lrotate(AVLNode node,AVLNode tempRootNode){
  117. AVLNode rotateNode = tempRootNode.getLeftNode();//旋转节点
  118. AVLNode rootNode = tempRootNode.getRootNode();//主根节点
  119. String type = "";
  120. if(rootNode!=null){//子树类型
  121. if(rootNode.getLeftNode()==tempRootNode){
  122. type="l";
  123. }else{
  124. type="r";
  125. }
  126. }
  127. AVLNode adjustNode = rotateNode.getRightNode();//调整节点
  128. rotateNode.setRightNode(tempRootNode);
  129. tempRootNode.setLeftNode(null);
  130. if(adjustNode!=null){
  131. tempRootNode.setLeftNode(adjustNode);
  132. }
  133. if(rootNode==null){
  134. rotateNode.setRootNode(null);
  135. this.rootNode = rotateNode;
  136. }
  137. if(type.equals("r")){
  138. rootNode.setRightNode(rotateNode);
  139. }else if(type.equals("l")){
  140. rootNode.setLeftNode(rotateNode);
  141. }
  142. }
  143.  
  144. /**
  145. * 查找最小不平衡的根节点
  146. * @author tomsnail
  147. * @date 2015年3月30日 下午5:40:55
  148. */
  149. private AVLNode findTempRootNode(AVLNode node){
  150. AVLNode noB = getNoBalance(node);
  151. if(noB==null){
  152. return null;
  153. }
  154. if(isTypeLL(noB)){
  155. bulidType = "ll";
  156. }else if(isTypeRR(noB)){
  157. bulidType = "rr";
  158. }else if(isTypeLR(noB)){
  159. bulidType = "lr";
  160. }else if(isTypeRL(noB)){
  161. bulidType = "rl";
  162. }
  163. return noB;
  164. }
  165. //左左类型
  166. private boolean isTypeLL(AVLNode noB){
  167. try {
  168. if(noB.getRightNode()==null&&noB.getLeftNode().getRightNode()==null&&!noB.getLeftNode().getLeftNode().hasSubNode()){
  169. return true;
  170. }
  171. if(noB.getRightNode()!=null&&noB.getLeftNode().getRightNode()!=null&&noB.getLeftNode().getLeftNode().hasSubNode()){
  172. return true;
  173. }
  174. } catch (Exception e) {
  175. }
  176. return false;
  177. }
  178. //右右类型
  179. private boolean isTypeRR(AVLNode noB){
  180. try {
  181. if(noB.getLeftNode()==null&&noB.getRightNode().getLeftNode()==null&&!noB.getRightNode().getRightNode().hasSubNode()){
  182. return true;
  183. }
  184. if(noB.getLeftNode()!=null&&noB.getRightNode().getLeftNode()!=null&&noB.getRightNode().getRightNode().hasSubNode()){
  185. return true;
  186. }
  187. } catch (Exception e) {
  188. }
  189. return false;
  190. }
  191. //左右类型
  192. private boolean isTypeLR(AVLNode noB){
  193. try {
  194. if(noB.getRightNode()==null&&noB.getLeftNode().getLeftNode()==null&&!noB.getLeftNode().getRightNode().hasSubNode()){
  195. return true;
  196. }
  197. if(noB.getRightNode()!=null&&noB.getLeftNode().getLeftNode()!=null&&noB.getLeftNode().getRightNode().hasSubNode()){
  198. return true;
  199. }
  200. } catch (Exception e) {
  201. }
  202. return false;
  203. }
  204. //右左类型
  205. private boolean isTypeRL(AVLNode noB){
  206. try {
  207. if(noB.getLeftNode()==null&&noB.getRightNode().getRightNode()==null&&!noB.getRightNode().getLeftNode().hasSubNode()){
  208. return true;
  209. }
  210. if(noB.getLeftNode()!=null&&noB.getRightNode().getRightNode()!=null&&noB.getRightNode().getLeftNode().hasSubNode()){
  211. return true;
  212. }
  213. } catch (Exception e) {
  214. }
  215. return false;
  216. }
  217.  
  218. //获取不平衡的根节点
  219. private AVLNode getNoBalance(AVLNode node){
  220. if(node.getRootNode()==null){
  221. return null;
  222. }else{
  223. if(!isBalance(node.getRootNode())){
  224. return node.getRootNode();
  225. }else{
  226. return getNoBalance(node.getRootNode());
  227. }
  228. }
  229. }
  230.  
  231. /**
  232. * 删除一个节点
  233. * @author tomsnail
  234. * @date 2015年3月30日 下午4:36:20
  235. */
  236. public void delete(int value){
  237. AVLNode wantDeleteNode = find(value);
  238. if(wantDeleteNode==null){
  239. return;
  240. }else{
  241. if(wantDeleteNode.getLeftNode()==null&&wantDeleteNode.getRightNode()==null){//删除节点没有左右子树
  242. AVLNode rootNode = wantDeleteNode.getRootNode();
  243. if(rootNode!=null){
  244. if(rootNode.getLeftNode()==wantDeleteNode){
  245. rootNode.setLeftNode(null);
  246. }else{
  247. rootNode.setRightNode(null);
  248. }
  249. reBuild(rootNode);
  250. }
  251. }else if(wantDeleteNode.getRightNode()==null){//删除节点只有左子树
  252. AVLNode rootNode = wantDeleteNode.getRootNode();
  253. if(rootNode!=null){
  254. if(rootNode.getLeftNode()==wantDeleteNode){
  255. rootNode.setLeftNode(wantDeleteNode.getLeftNode());
  256. }else{
  257. rootNode.setRightNode(wantDeleteNode.getLeftNode());
  258. }
  259. wantDeleteNode.setLeftNode(null);
  260. reBuild(rootNode);
  261. }
  262. }else if(wantDeleteNode.getLeftNode()==null){//删除节点只有右子树
  263. AVLNode rootNode = wantDeleteNode.getRootNode();
  264. if(rootNode!=null){
  265. if(rootNode.getRightNode()==wantDeleteNode){
  266. rootNode.setLeftNode(wantDeleteNode.getRightNode());
  267. }else{
  268. rootNode.setRightNode(wantDeleteNode.getRightNode());
  269. }
  270. wantDeleteNode.setRightNode(null);
  271. reBuild(rootNode);
  272. }
  273. }else {//删除节点有左右子树
  274. AVLNode maxNode = getLeftMaxValueNode(wantDeleteNode.getLeftNode());//找到节点左子树最大值的节点
  275. AVLNode rootMaxNode = maxNode.getRootNode();//获得该节点的父节点
  276. if(maxNode.getLeftNode()!=null){//如果最大值节点有左子树,则将最大值节点的父节点的右子树设为它
  277. rootMaxNode.setRightNode(maxNode.getLeftNode());
  278. maxNode.setLeftNode(null);
  279. }else{//否则置空
  280. rootMaxNode.setRightNode(null);
  281. }
  282. wantDeleteNode.setValue(maxNode.getValue());//把要删除节点的值用最大值节点的值替换
  283. maxNode=null;//引用置空
  284. reBuild(rootMaxNode);
  285. }
  286. }
  287. }
  288. //得到左子树最大值节点
  289. private AVLNode getLeftMaxValueNode(AVLNode node){
  290. if(node!=null&&node.getRightNode()!=null){
  291. return getLeftMaxValueNode(node.getRightNode());
  292. }else{
  293. return node;
  294. }
  295. }
  296.  
  297. /**
  298. * 查找一个节点
  299. * @author tomsnail
  300. * @date 2015年3月30日 下午4:36:35
  301. */
  302. public AVLNode find(int value){
  303. return findWith2(rootNode,value);
  304. }
  305. private AVLNode findWith2(AVLNode node,int value){
  306. if(node==null){
  307. return null;
  308. }
  309. System.out.println(node.getValue());
  310. if(node.getValue()>value){
  311. return findWith2(node.getLeftNode(),value);
  312. }else if(node.getValue()<value){
  313. return findWith2(node.getRightNode(),value);
  314. }else{
  315. return node;
  316. }
  317. }
  318.  
  319. /**
  320. * 中序遍历
  321. * @author tomsnail
  322. * @date 2015年3月31日 下午6:23:05
  323. */
  324. public void midScan(AVLNode node){
  325. if(node==null){
  326. return;
  327. }
  328. midScan(node.getLeftNode());
  329. System.out.println(node.getValue());
  330. midScan(node.getRightNode());
  331. }
  332.  
  333. public AVLNode getRootNode() {
  334. return rootNode;
  335. }
  336.  
  337. public static void main(String[] args) {
  338. int[] is = new int[]{10,11,23,3,5,44,32,4,6,18,19,7,8,70,50,60,40,55,65,53,80};//10,11,23,3,5,44,32,4,6,18,19,7,8,70,50,60,40,55,65,53,80
  339. AVLTree tree = new AVLTree();
  340. for(int i=0;i<is.length;i++){
  341. tree.add(is[i]);
  342. }
  343. System.out.println(tree.getRootNode().getValue());
  344. System.out.println("----------------------------");
  345. tree.midScan(tree.getRootNode());
  346. tree.delete(4);
  347. System.out.println(isBalance(tree.getRootNode()));
  348. System.out.println();
  349. //tree.find(40);
  350. }
  351.  
  352. public static int depth(AVLNode node){
  353. if(node==null){
  354. return 0;
  355. }else{
  356. int ld = depth(node.getLeftNode());
  357. int rd = depth(node.getRightNode());
  358. return 1 + (ld >rd ? ld : rd);
  359. }
  360. }
  361.  
  362. public static boolean isBalance(AVLNode node){
  363. if (node==null)
  364. return true;
  365. int dis = depth(node.getLeftNode()) - depth(node.getRightNode());
  366. if (dis>1 || dis<-1 )
  367. return false;
  368. else
  369. return isBalance(node.getLeftNode()) && isBalance(node.getRightNode());
  370. }
  371. }
  372. class AVLNode{
  373. private int value;
  374. private AVLNode leftNode;
  375. private AVLNode rightNode;
  376. private AVLNode rootNode;
  377. public int getValue() {
  378. return value;
  379. }
  380. public void setValue(int value) {
  381. this.value = value;
  382. }
  383. public AVLNode getLeftNode() {
  384. return leftNode;
  385. }
  386. public void setLeftNode(AVLNode leftNode) {
  387. this.leftNode = leftNode;
  388. if(leftNode!=null){
  389. leftNode.setRootNode(this);
  390. }
  391. }
  392. public AVLNode getRightNode() {
  393. return rightNode;
  394. }
  395. public void setRightNode(AVLNode rightNode) {
  396. this.rightNode = rightNode;
  397. if(rightNode!=null){
  398. rightNode.setRootNode(this);
  399. }
  400. }
  401.  
  402. public AVLNode getRootNode() {
  403. return rootNode;
  404. }
  405. public void setRootNode(AVLNode rootNode) {
  406. this.rootNode = rootNode;
  407. }
  408.  
  409. public boolean hasSubNode(){
  410. if(this.leftNode!=null||this.rightNode!=null){
  411. return true;
  412. }else{
  413. return false;
  414. }
  415. }
  416.  
  417. public AVLNode(){
  418. }
  419. public AVLNode(int value){
  420. this.value = value;
  421. }
  422. }

树——平衡二叉树插入和查找的JAVA实现(2):增加删除方法的更多相关文章

  1. 树——平衡二叉树插入和查找的JAVA实现

    package com.tomsnail.data.tree; /** * AVL二叉平衡树 * @author tomsnail * @date 2015年3月30日 下午4:35:50 */ pu ...

  2. 数据结构系列之2-3-4树的插入、查找、删除和遍历完整版源代码实现与分析(dart语言实现)

    本文属于原创,转载请注明来源. 在上一篇博文中,详细介绍了2-3树的操作(具体地址:https://www.cnblogs.com/outerspace/p/10861488.html),那么对于更多 ...

  3. 数据结构系列之2-3树的插入、查找、删除和遍历完整版代码实现(dart语言实现)

    弄懂了二叉树以后,再来看2-3树.网上.书上看了一堆文章和讲解,大部分是概念,很少有代码实现,尤其是删除操作的代码实现.当然,因为2-3树的特性,插入和删除都是比较复杂的,因此经过思考,独创了删除时分 ...

  4. DS-二叉排序树的插入、查找和删除

    2019-12-02(菜鸡开始学习了...) Data Structure 之 二叉排序树 二叉排序树是给定一个节点后,接下来插入的数如果比它大就会放到它的右孩子那边,比它小就会放到它的左孩子那边. ...

  5. 萌新笔记——C++里创建 Trie字典树(中文词典)(二)(插入、查找、导入、导出)

    萌新做词典第二篇,做得不好,还请指正,谢谢大佬! 做好了插入与遍历功能之后,我发现最基本的查找功能没有实现,同时还希望能够把内存的数据存入文件保存下来,并可以从文件中导入词典.此外,数据的路径是存在配 ...

  6. C++里创建 Trie字典树(中文词典)(二)(插入、查找、导入、导出)

    萌新做词典第二篇,做得不好,还请指正,谢谢大佬! 做好了插入与遍历功能之后,我发现最基本的查找功能没有实现,同时还希望能够把内存的数据存入文件保存下来,并可以从文件中导入词典.此外,数据的路径是存在配 ...

  7. Java手写简单Linkedlist一(包括增加,插入,查找,toString,remove功能)

    @Java300 学习总结 一.自定义节点 LinkList底层为双向链表.特点为查询效率低,但增删效率高,线程不安全. 链表数据储存在节点,且每个节点有指向上个和下个节点的指针. 创建ggLinke ...

  8. 树·AVL树/平衡二叉树

    1.AVL树 带有平衡条件的二叉查找树,所以它必须满足条件: 1 是一棵二叉查找树 2 满足平衡条件 1.1 平衡条件: 1)严格的平衡条件:每个节点都必须有相同高度的左子树和右子树(过于严格而不被使 ...

  9. 【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介

    B  树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: ...

随机推荐

  1. hashCode与equals的作用与区别及应当注意的细节

    最近去面试了几家公司,被问到hashCode的作用,虽然回答出来了,但是自己还是对hashCode和equals的作用一知半解的,所以决定把它们研究一下. 以前写程序一直没有注意hashCode的作用 ...

  2. Mac中遇到的Eclipse连接不上mySql的问题

    1.首先我们在eclipse中连接数据库的过程中,遇到的问题就是如上图.开始百度Communications link failure 这几个关键字.得到的结果基本上就是基本配置参数wait_time ...

  3. Druid——阿里巴巴的开源项目(关于数据库连接、监控)

    相关文章 0.Druid首页——jdbc连接池,监控组件 1.阿里巴巴的开源项目Druid(关于数据库连接) 2.ITeye谈Druid 3.DBCP(DataBase connection pool ...

  4. CentOS搭建git服务器实测

    Git 可以使用四种主要的协议来传输数据:本地传输,SSH 协议,Git 协议和 HTTP 协议 1,安装: CentOS/Fedora: yum install git Ubuntu/Debian: ...

  5. linux查看磁盘挂载的三种方法

    第一种方法:使用df命令,例如: orientalson:/home # df Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda ...

  6. arcgis10.0 切片并发布服务及验证

    1.切片参考网址:https://jingyan.baidu.com/article/fa4125accc6bef28ac7092d7.html 2.通过下面代码验证  参考网址https://www ...

  7. mfc 小程序---在系统菜单中添加菜单项

    1建立一个对话框工程:在dlg类里定义一个菜单指针m_pMenu,在对话框OnInitDialog函数里添加代码: m_pMenu=GetSystemMenu(FALSE);//获取系统菜单的指针 m ...

  8. CGI模式下的bug

    一般情况下$_SERVER['PHP_SELF']  与 $_SERVER['SCRIPT_NAME']  没有什么区别,但是如果PHP是以CGI模式运行的话两者就有差异 建议使用$_SERVER[' ...

  9. Mybatis中resultMap的基础配置

    一.概述 resultMap 元素是 MyBatis 中最重要最强大的元素.它就是让你远离 90%的需要从结果集中取出数据的 JDBC 代码的那个东西,而且在一些情形下允许你做一些 JDBC 不支持的 ...

  10. Android笔记之Retrofit与RxJava的组合

    依赖 implementation 'com.squareup.retrofit2:retrofit:2.5.0' implementation 'com.squareup.retrofit2:con ...