二叉树

比如我要依次插入10、3、1、8、23、15、28。先插入10作为根节点:

然后插入3,比10小,放在左边:

再插入1,比10和3小,放在3左边:

再插入8,比10小,比3大,放在3右边:

再插入23,比10大,放在10右边:

再插入15,比10大,比23小,放在23左边:

最后插入28,比10和23大,放在23右边:

代码实现:

  1. package com.demo.tree;
  2.  
  3. import java.util.LinkedList;
  4. import java.util.Queue;
  5.  
  6. public class BinaryTree {
  7.  
  8. public static void main(String[] args){
  9. BinaryTree tree = new BinaryTree();
  10. tree.batchInsert(new int[]{10,3,1,8,23,15,28});
  11. tree.prePrint();
  12. tree.midPrint();
  13. tree.postPrint();
  14. tree.tierPrint();
  15. tree.printDepth();
  16. }
  17.  
  18. private Node root;
  19.  
  20. /**
  21. * 节点
  22. */
  23. private class Node{
  24. int data; // 数据
  25. Node left; // 左指针
  26. Node right; // 右指针
  27.  
  28. private Node(int data) {
  29. this.data = data;
  30. this.left = null;
  31. this.right = null;
  32. }
  33. }
  34.  
  35. /**
  36. * 插入
  37. * @param data
  38. */
  39. public void insert(int data){
  40. Node newData = new Node(data);
  41. if (root == null){
  42. root = newData;
  43. }else{
  44. Node parent = root;
  45. while (true){
  46. if (data < parent.data){
  47. // 如果左边为空,那新数据就直接放在这
  48. if (parent.left == null){
  49. parent.left = newData;
  50. break;
  51. }
  52. // 进入左节点
  53. parent = parent.left;
  54. }else{
  55. // 如果右边为空,那新数据就直接放在这
  56. if (parent.right == null){
  57. parent.right = newData;
  58. break;
  59. }
  60. // 进入右节点
  61. parent = parent.right;
  62. }
  63. }
  64. }
  65. }
  66.  
  67. /**
  68. * 批量插入
  69. * @param arr
  70. */
  71. public void batchInsert(int[] arr){
  72. for (int data : arr){
  73. insert(data);
  74. }
  75. }
  76.  
  77. /**
  78. * 前序遍历
  79. */
  80. public void prePrint(){
  81. System.out.print("前序遍历\t");
  82. if (root != null){
  83. pre(root);
  84. }
  85. System.out.println();
  86. }
  87.  
  88. private void pre(Node node){
  89. if (node != null) {
  90. System.out.print(node.data + "\t");
  91. pre(node.left);
  92. pre(node.right);
  93. }
  94. }
  95.  
  96. /**
  97. * 中序遍历
  98. */
  99. public void midPrint(){
  100. System.out.print("中序遍历\t");
  101. if (root != null){
  102. mid(root);
  103. }
  104. System.out.println();
  105. }
  106.  
  107. private void mid(Node node){
  108. if (node != null) {
  109. mid(node.left);
  110. System.out.print(node.data + "\t");
  111. mid(node.right);
  112. }
  113. }
  114.  
  115. /**
  116. * 后序遍历
  117. */
  118. public void postPrint(){
  119. System.out.print("后序遍历\t");
  120. if (root != null){
  121. post(root);
  122. }
  123. System.out.println();
  124. }
  125.  
  126. private void post(Node node){
  127. if (node != null) {
  128. post(node.left);
  129. post(node.right);
  130. System.out.print(node.data + "\t");
  131. }
  132. }
  133.  
  134. /**
  135. * 层序遍历,利用队列先进先出
  136. */
  137. public void tierPrint(){
  138. if (root != null){
  139. Queue<Node> queue = new LinkedList<>();
  140. queue.add(root);
  141. System.out.print("层序遍历\t");
  142. while (!queue.isEmpty()){
  143. Node temp = queue.remove();
  144. System.out.print(temp.data + "\t");
  145. if (temp.left != null){
  146. // 左节点不为空,放进队列
  147. queue.add(temp.left);
  148. }
  149. if (temp.right != null){
  150. // 右节点不为空,放进队列
  151. queue.add(temp.right);
  152. }
  153. }
  154. }
  155. System.out.println();
  156. }
  157.  
  158. /**
  159. * 求树高
  160. */
  161. public void printDepth(){
  162. if (root == null){
  163. System.out.println(0);
  164. }else{
  165. System.out.println("树高\t" + getDepth(root));
  166. }
  167. }
  168.  
  169. private int getDepth(Node node){
  170. if (node == null){
  171. return 0;
  172. }
  173. return Math.max(getDepth(node.left), getDepth(node.right))+1;
  174. }
  175.  
  176. }

测试:

平衡二叉树

前面的二叉树有个问题,如果我们按照顺序插入,那么这个树就会退化成一个线性链表,这个时候引入平衡二叉树来解决。

平衡二叉树要维持平衡需要旋转操作

LL型(在A的左孩子(L)的左子树(L)上插入新结点)

过程:

1. 将A的左孩子B提升为根节点

2. 将A降级为B的右孩子

3. 将B的右孩子调整为A的左孩子

RR型(在A的右孩子(R)的右子树(R)上插入新结点)

过程:

1. 将A的右孩子B提升为根节点

2. 将A降级为B的左孩子

3. 将B的左孩子调整为A的右孩子

LR型(在A的左孩子(L)的右子树(R)上插入新结点)【插入在C任意一颗子树都可以】

过程:

1. B、C节点左旋。

2. A、C节点右旋。

RL型(在A的右孩子(R)的左子树(L)上插入新结点)【插入在C任意一颗子树都可以】

过程:

1. B、C节点右旋。

2. A、C节点左旋。

插入步骤图解

平衡二叉树的插入,例如依次插入:8,6,3,4,5,20,15,23,28,1,2

插入8先作为根节点,插入6依然平衡,插入3不平衡,进行一次右旋(LL)

插入4依然平衡,插入5不平衡,进行左旋(RR)

插入20依然平衡,插入15不平衡,先右旋再左旋(RL)

插入23依然平衡,插入28不平衡,进行一次左旋(RR)

插入1依然平衡,插入2不平衡,先左旋再右旋(LR)

代码

  1. package com.demo.tree;
  2.  
  3. import java.util.LinkedList;
  4. import java.util.Queue;
  5.  
  6. public class BalancedBinaryTree {
  7.  
  8. public static void main(String[] args){
  9. BalancedBinaryTree tree = new BalancedBinaryTree();
  10. tree.batchInsert(new int[]{8,6,3,4,5,20,15,23,28,1,2});
  11. tree.tierPrint();
  12. }
  13.  
  14. private Node root;
  15.  
  16. /**
  17. * 节点
  18. */
  19. private class Node{
  20. int data; // 数据
  21. Node left; // 左指针
  22. Node right; // 右指针
  23.  
  24. private Node(int data) {
  25. this.data = data;
  26. this.left = null;
  27. this.right = null;
  28. }
  29. }
  30.  
  31. /**
  32. * 右旋操作(左孩子的左子树插入节点)
  33. * @param p
  34. */
  35. private Node rightRotate(Node p){
  36. Node temp = p.left; // temp指向p的左子树
  37. p.left = temp.right; // p的左子树指向temp的右子树
  38. temp.right = p;
  39. return temp;
  40. }
  41.  
  42. /**
  43. * 左旋操作(右孩子的右子树插入节点)
  44. * @param p
  45. */
  46. private Node leftRotate(Node p){
  47. Node temp = p.right; // temp指向p的右子树
  48. p.right = temp.left; // p的右子树指向temp的左子树
  49. temp.left = p;
  50. return temp;
  51. }
  52.  
  53. /**
  54. * 先左旋再右旋(左孩子的右子树插入节点)
  55. * @param p
  56. */
  57. private Node leftRightRotate(Node p){
  58. p.left = leftRotate(p.left);
  59. return rightRotate(p);
  60. }
  61.  
  62. /**
  63. * 先右旋再左旋(右孩子的左子树插入节点)
  64. * @param p
  65. */
  66. private Node rightLeftRotate(Node p){
  67. p.right = rightRotate(p.right);
  68. return leftRotate(p);
  69. }
  70.  
  71. /**
  72. * 树高
  73. * @param node
  74. * @return
  75. */
  76. private int getDepth(Node node){
  77. if (node == null){
  78. return 0;
  79. }
  80. return Math.max(getDepth(node.left), getDepth(node.right))+1;
  81. }
  82.  
  83. /**
  84. * 平衡因子(左高:>1 等高:0 右高:<-1)
  85. * @return
  86. */
  87. public int balanceFactor(Node node){
  88. if (node == null){
  89. return 0;
  90. }
  91. return getDepth(node.left) - getDepth(node.right);
  92. }
  93.  
  94. /**
  95. * 插入
  96. * @param node
  97. * @param data
  98. */
  99. public Node insert(Node node, int data){
  100. Node newData = new Node(data);
  101. if (node == null){
  102. return newData;
  103. }
  104. if (data < node.data){
  105. node.left = insert(node.left, data);
  106. }else if (data > node.data){
  107. node.right = insert(node.right, data);
  108. }else{
  109. return node;
  110. }
  111. int bf = balanceFactor(node);
  112.  
  113. if (bf > 1 && data < node.left.data){
  114. // LL
  115. System.out.println("LL" + data);
  116. return rightRotate(node);
  117. }else if (bf < -1 && data > node.right.data){
  118. // RR
  119. System.out.println("RR" + data);
  120. return leftRotate(node);
  121. }else if (bf > 1 && data > node.left.data){
  122. // LR
  123. System.out.println("LR" + data);
  124. return leftRightRotate(node);
  125. }else if (bf < -1 && data < node.right.data){
  126. // RL
  127. System.out.println("RL" + data);
  128. return rightLeftRotate(node);
  129. }
  130. return node;
  131. }
  132.  
  133. /**
  134. * 批量插入
  135. * @param arr
  136. */
  137. public void batchInsert(int[] arr){
  138. for (int data : arr){
  139. root = insert(root, data);
  140. }
  141. }
  142.  
  143. /**
  144. * 前序遍历
  145. */
  146. public void prePrint(){
  147. System.out.print("前序遍历\t");
  148. if (root != null){
  149. pre(root);
  150. }
  151. System.out.println();
  152. }
  153.  
  154. private void pre(Node node){
  155. if (node != null) {
  156. System.out.print(node.data + "\t");
  157. pre(node.left);
  158. pre(node.right);
  159. }
  160. }
  161.  
  162. /**
  163. * 中序遍历
  164. */
  165. public void midPrint(){
  166. System.out.print("中序遍历\t");
  167. if (root != null){
  168. mid(root);
  169. }
  170. System.out.println();
  171. }
  172.  
  173. private void mid(Node node){
  174. if (node != null) {
  175. mid(node.left);
  176. System.out.print(node.data + "\t");
  177. mid(node.right);
  178. }
  179. }
  180.  
  181. /**
  182. * 后序遍历
  183. */
  184. public void postPrint(){
  185. System.out.print("后序遍历\t");
  186. if (root != null){
  187. post(root);
  188. }
  189. System.out.println();
  190. }
  191.  
  192. private void post(Node node){
  193. if (node != null) {
  194. post(node.left);
  195. post(node.right);
  196. System.out.print(node.data + "\t");
  197. }
  198. }
  199.  
  200. /**
  201. * 层序遍历,利用队列先进先出
  202. */
  203. public void tierPrint(){
  204. if (root != null){
  205. Queue<Node> queue = new LinkedList<>();
  206. queue.add(root);
  207. System.out.print("层序遍历\t");
  208. while (!queue.isEmpty()){
  209. Node temp = queue.remove();
  210. System.out.print(temp.data + "\t");
  211. if (temp.left != null){
  212. // 左节点不为空,放进队列
  213. queue.add(temp.left);
  214. }
  215. if (temp.right != null){
  216. // 右节点不为空,放进队列
  217. queue.add(temp.right);
  218. }
  219. }
  220. }
  221. }
  222.  
  223. }

二叉树 & 平衡二叉树 算法(Java实现)的更多相关文章

  1. 找出 int 数组的平衡点 & 二叉树 / 平衡二叉树 / 满二叉树 / 完全二叉树 / 二叉查找树

    找出 int 数组的平衡点 左右两边和相等, 若存在返回平衡点的值(可能由多个); 若不存在返回 -1; ``java int [] arr = {2,3,4,2,4}; ```js const ar ...

  2. 无向图的最短路径算法JAVA实现

    一,问题描述 给出一个无向图,指定无向图中某个顶点作为源点.求出图中所有顶点到源点的最短路径. 无向图的最短路径其实是源点到该顶点的最少边的数目. 本文假设图的信息保存在文件中,通过读取文件来构造图. ...

  3. 无向图的最短路径算法JAVA实现(转)

    一,问题描述 给出一个无向图,指定无向图中某个顶点作为源点.求出图中所有顶点到源点的最短路径. 无向图的最短路径其实是源点到该顶点的最少边的数目. 本文假设图的信息保存在文件中,通过读取文件来构造图. ...

  4. 归并排序算法 java 实现

    归并排序算法 java 实现 可视化对比十多种排序算法(C#版) [直观学习排序算法] 视觉直观感受若干常用排序算法 算法概念 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Di ...

  5. 快速排序算法 java 实现

    快速排序算法 java 实现 快速排序算法Java实现 白话经典算法系列之六 快速排序 快速搞定 各种排序算法的分析及java实现 算法概念 快速排序是C.R.A.Hoare于1962年提出的一种划分 ...

  6. 堆排序算法 java 实现

    堆排序算法 java 实现 白话经典算法系列之七 堆与堆排序 Java排序算法(三):堆排序 算法概念 堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特 ...

  7. Atitit 电子商务订单号码算法(java c# php js 微信

    Atitit 电子商务订单号码算法(java c# php js  微信 1.1. Js版本的居然钱三爷里面没有..只好自己实现了. 1.2. 订单号标准化...长度16位 1.3. 订单号的结构 前 ...

  8. 关于Leetcode上二叉树的算法总结

    二叉树,结构很简单,只是比单链表复杂了那么一丢丢而已.我们先来看看它们结点上的差异: /* 单链表的结构 */ struct SingleList{ int element; struct Singl ...

  9. 基于FP-Tree的关联规则FP-Growth推荐算法Java实现

    基于FP-Tree的关联规则FP-Growth推荐算法Java实现 package edu.test.ch8; import java.util.ArrayList; import java.util ...

随机推荐

  1. Windows下VS Code打开黑屏解决办法(这样真的行)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qq_42421611/article/d ...

  2. Delphi中destroy, free, freeAndNil, release用法和区别

    Delphi中destroy, free, freeAndNil, release用法和区别 1)destroy:虚方法 释放内存,在Tobject中声明为virtual,通常是在其子类中overri ...

  3. MYSQL中IN,INSTR,FIND_IN_SET函数效率比较(转)

    今天写代码时前台传过来类似‘1,2,3,4,5,6’的字符串,这种情况直接用IN是无效的,需要把字符串分割成数组或者组装成列表,然后再利用mabatis的foreach函数 <select id ...

  4. SAP云平台和第三方CRM解决方案(火锅)互联

    光看封面配图,这篇文章很容易被误认为在讲成都的美食之一:火锅. SAP成都研究院坐落在被联合国教科文组织授予过"美食之都"称号的成都,所在的天府软件园,半径1公里左右星罗棋布着很多 ...

  5. 个人项目-wc

    个人项目-WC   (C语言) 一.Github地址:https://github.com/Lin-J-F/WC 二.PSP表格 PSP2.1 Personal Software Process St ...

  6. js 字符串 有没有 像C# @ 那种 换行也可以显示的方法 \

  7. 性能测试-MySQL性能查看(转)

    mysql查看数据库性能常用命令 mysql> show global status; 可以列出MySQL服务器运行各种状态值,另外,查询MySQL服务器配置信息语句: mysql> sh ...

  8. linux 下按照文件名模糊查找文件

    fnmatch int fnmatch(const char *pattern, const char *string, int flags); 参数说明 FNM_NOESCAPE 如果这个标志设置了 ...

  9. Qemu-4.1 桥接网络设置

    参考: [qemu] qemu旧的net参数已经不再可用了,新的这样用. QEMU's new -nic command line option 用Qemu模拟vexpress-a9 --- 配置 q ...

  10. windows 给mysql安装innodb引擎

    1.启用InnoDB    打开my.ini文件,找到[skip-innodb],在前面加# 2.更改数据库默认引擎为InnoDB    打开my.ini文件,更改[default-storage-e ...