1. package com.atguigu.tree;
    2. /**
    3. * 二叉树
    4. *
    5. * @author Dxkstart
    6. * @create 2021-10-17-14:32
    7. */
    8. public class BinaryTreeDemo {
    9. public static void main(String[] args) {
    10. //先需要创建一棵二叉树
    11. BinaryTree binaryTree = new BinaryTree();
    12. //创建需要的节点
    13. HeroNode root = new HeroNode(1, "宋江");
    14. HeroNode node2 = new HeroNode(2, "吴用");
    15. HeroNode node3 = new HeroNode(3, "卢俊义");
    16. HeroNode node4 = new HeroNode(4, "林冲");
    17. HeroNode node5 = new HeroNode(5, "关胜");
    18. //说明:
    19. //我们先手动创建二叉树,后面我们学习递归的方式创建二叉树
    20. root.setLeft(node2);
    21. root.setRight(node3);
    22. node3.setRight(node4);
    23. node3.setLeft(node5);
    24. binaryTree.setRoot(root);
    25. /* //测试遍历
    26. System.out.println("前序遍历");//12354
    27. binaryTree.preOrder1();
    28. System.out.println("中序遍历");//21534
    29. binaryTree.infixOrder1();
    30. System.out.println("后序遍历");//25431
    31. binaryTree.postOrder1();
    32. //测试查找
    33. System.out.println("前序遍历查找~");//比较了4次
    34. HeroNode resNode = binaryTree.preOrderSearch(5);
    35. if (resNode != null) {
    36. System.out.printf("找到了,信息为:no=%d name=%s \n", resNode.getNo(), resNode.getName());
    37. } else {
    38. System.out.println("没有找到");
    39. }
    40. System.out.println("中序遍历查找~");//比较了3次
    41. HeroNode resNode2 = binaryTree.infixOrderSearch(5);
    42. if (resNode2 != null) {
    43. System.out.printf("找到了,信息为:no=%d name=%s \n", resNode2.getNo(), resNode2.getName());
    44. } else {
    45. System.out.println("没有找到");
    46. }
    47. System.out.println("后序遍历查找~");//比较了2次
    48. HeroNode resNode3 = binaryTree.postOrderSearch(5);
    49. if (resNode3 != null) {
    50. System.out.printf("找到了,信息为:no=%d name=%s \n", resNode3.getNo(), resNode3.getName());
    51. } else {
    52. System.out.println("没有找到");
    53. }
    54. */
    55. //测试删除
    56. System.out.println("删除前,前序遍历");
    57. binaryTree.preOrder1();
    58. // binaryTree.delete(5); //1234
    59. binaryTree.delete(3); //12
    60. System.out.println("删除后,前序遍历");
    61. binaryTree.preOrder1();
    62. }
    63. }
    64. //定义BinaryTree 二叉树
    65. class BinaryTree {
    66. private HeroNode root;
    67. public void setRoot(HeroNode root) {
    68. this.root = root;
    69. }
    70. //*******遍历**************************
    71. //前序遍历
    72. public void preOrder1() {
    73. if (this.root != null) {
    74. this.root.preOrder();
    75. } else {
    76. System.out.println("二叉树为空,无法遍历");
    77. }
    78. }
    79. //中序遍历
    80. public void infixOrder1() {
    81. if (this.root != null) {
    82. this.root.infixOrder();
    83. } else {
    84. System.out.println("二叉树为空,无法遍历");
    85. }
    86. }
    87. //后序遍历
    88. public void postOrder1() {
    89. if (this.root != null) {
    90. this.root.postOrder();
    91. } else {
    92. System.out.println("二叉树为空,无法遍历");
    93. }
    94. }
    95. //*******查找**************************
    96. //前序遍历查找
    97. public HeroNode preOrderSearch(int no) {
    98. if (root != null) {
    99. return root.postOrderSearch(no);
    100. } else {
    101. return null;
    102. }
    103. }
    104. //中序遍历查找
    105. public HeroNode infixOrderSearch(int no) {
    106. if (root != null) {
    107. return root.infixOrderSearch(no);
    108. } else {
    109. return null;
    110. }
    111. }
    112. //后序遍历查找
    113. public HeroNode postOrderSearch(int no) {
    114. if (root != null) {
    115. return root.postOrderSearch(no);
    116. } else {
    117. return null;
    118. }
    119. }
    120. //*******删除**************************
    121. public void delete(int no){
    122. if (root != null){
    123. //如果只有一个root节点,则这里需要立即判断root是否为待删除节点
    124. if (root.getNo() == no){
    125. root = null;
    126. }else {
    127. root.delete(no);
    128. }
    129. }else {
    130. System.out.println("空树!");
    131. }
    132. }
    133. }
    134. //先创建HeroNode节点
    135. class HeroNode {
    136. private int no;
    137. private String name;
    138. private HeroNode left;//默认null
    139. private HeroNode right;//默认null
    140. public HeroNode(int no, String name) {
    141. this.no = no;
    142. this.name = name;
    143. }
    144. public int getNo() {
    145. return no;
    146. }
    147. public void setNo(int no) {
    148. this.no = no;
    149. }
    150. public String getName() {
    151. return name;
    152. }
    153. public void setName(String name) {
    154. this.name = name;
    155. }
    156. public HeroNode getLeft() {
    157. return left;
    158. }
    159. public void setLeft(HeroNode left) {
    160. this.left = left;
    161. }
    162. public HeroNode getRight() {
    163. return right;
    164. }
    165. public void setRight(HeroNode right) {
    166. this.right = right;
    167. }
    168. @Override
    169. public String toString() {
    170. return "HeroNode{" +
    171. "no=" + no +
    172. ", name='" + name + '\'' +
    173. '}';
    174. }
    175. //*******遍历**************************
    176. //前序遍历方法
    177. public void preOrder() {
    178. System.out.println(this);//先输出父节点
    179. //递归向左子树遍历
    180. if (this.left != null) {
    181. this.left.preOrder();
    182. }
    183. //递归向右子树遍历
    184. if (this.right != null) {
    185. this.right.preOrder();
    186. }
    187. }
    188. //中序遍历方法
    189. public void infixOrder() {
    190. //递归向左子树中序遍历
    191. if (this.left != null) {
    192. this.left.infixOrder();
    193. }
    194. //输出父节点
    195. System.out.println(this);
    196. //递归向右子树中序遍历
    197. if (this.right != null) {
    198. this.right.infixOrder();
    199. }
    200. }
    201. //后序遍历方法
    202. public void postOrder() {
    203. if (this.left != null) {
    204. this.left.postOrder();
    205. }
    206. if (this.right != null) {
    207. this.right.postOrder();
    208. }
    209. System.out.println(this);
    210. }
    211. //*******查找**************************
    212. //前序遍历查找
    213. /**
    214. * @param no 查找no
    215. * @return 如果找到就返回该Node,如果没有找到,就返回null
    216. */
    217. public HeroNode preOrderSearch(int no) {
    218. //比较当前节点是不是
    219. if (this.no == no) {
    220. return this;
    221. }
    222. //1.则判断当前节点的左子节点是否为空,如果不为空,则递归前序查找
    223. //2.如果左递归前序查找,找到节点,则返回
    224. HeroNode resNode = null;
    225. if (this.left != null) {
    226. resNode = this.left.preOrderSearch(no);
    227. }
    228. if (resNode != null) {//说明我们左子树找到
    229. return resNode;
    230. }
    231. //1.左递归前序查找,找到节点,则返回,否则继续判断
    232. //2.当前的节点的右子节点是否为空,如果不为空,则继续向右递归前序查找
    233. if (this.right != null) {
    234. resNode = this.right.preOrderSearch(no);
    235. }
    236. return resNode;
    237. }
    238. //中序遍历查找
    239. public HeroNode infixOrderSearch(int no) {
    240. HeroNode resNode = null;
    241. //判断当前节点的左子节点是否为空,如果不为空,则递归中序查找
    242. if (this.left != null) {
    243. resNode = this.left.infixOrderSearch(no);
    244. }
    245. if (resNode != null) {
    246. return resNode;
    247. }
    248. //如果没找到,就和当前节点比较,如果是则返回当前节点
    249. if (this.no == no) {
    250. return this;
    251. }
    252. //否则继续进行右递归的中序查找
    253. if (this.right != null) {
    254. resNode = this.right.infixOrderSearch(no);
    255. }
    256. return resNode;
    257. }
    258. //后序遍历查找
    259. public HeroNode postOrderSearch(int no) {
    260. HeroNode resNode = null;
    261. //判断当前节点的左子节点是否为空,如果不为空,则递归后序查找
    262. if (this.left != null) {
    263. resNode = this.left.infixOrderSearch(no);
    264. }
    265. if (resNode != null) {
    266. return resNode;
    267. }
    268. //如果左子树没有找到,则向柚子树递归进行后序遍历查找
    269. if (this.right != null) {
    270. resNode = this.right.infixOrderSearch(no);
    271. }
    272. if (resNode != null) {
    273. return resNode;
    274. }
    275. //如果左右字数都没有找到,就比较当前节点是不是
    276. if (this.no == no) {
    277. resNode = this;
    278. }
    279. return resNode;
    280. }
    281. //*******删除**************************
    282. //递归删除节点
    283. //1.如果删除的节点是叶子节点,则删除该节点
    284. //2.如果删除的节点是非叶子节点,则删除该子树
    285. /**
    286. * 思路:
    287. * 1.因为我们的二叉树是单向的,所以我们是判断当前节点的子节点是否为待删除节点,而不能去判断当前节点是否为待删除节点
    288. * 2.如果当前节点的左子节点不为空,并且左子节点就是待删除节点,就将this.left = null;并且返回(结束递归删除)
    289. * 3.如果当前节点的右子节点不为空,并且右子节点就是待删除节点,就将this.right = null;并且返回(结束递归删除)
    290. * 4.如果2,3步没有删除节点,name我们就需要向左子树进行递归删除
    291. * 5.如果第4步也没有删除节点,则应当向右子树进行递归删除
    292. * @param no
    293. */
    294. public void delete(int no){
    295. //2.
    296. if(this.left != null && this.left.no == no){
    297. this.left = null;
    298. return;
    299. }
    300. //3.
    301. if(this.right != null && this.right.no == no){
    302. this.right = null;
    303. return;
    304. }
    305. //4.
    306. if (this.left != null){
    307. this.left.delete(no);
    308. }
    309. //5.
    310. if (this.right != null){
    311. this.right.delete(no);
    312. }
    313. }
    314. }