二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),也称二叉搜索树。二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
    (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
    (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
    (3)左、右子树也分别为二叉排序树;

    二叉排序树 - 图1

    1. /**
    2. * 《二叉排序树》
    3. * 61
    4. * / \
    5. * 55 87
    6. * / \
    7. * 42 58
    8. */
    9. public class BinarySortTree {
    10. /**
    11. * 根结点
    12. */
    13. private TreeNode rootNode;
    14. /**
    15. * 树结点
    16. */
    17. class TreeNode {
    18. /**
    19. * 结点值
    20. */
    21. private int value;
    22. /**
    23. * 左子结点
    24. */
    25. private TreeNode left;
    26. /**
    27. * 左子结点
    28. */
    29. private TreeNode right;
    30. public TreeNode(int value) {
    31. this.value = value;
    32. }
    33. /**
    34. * 中序遍历
    35. */
    36. public void middleOrder() {
    37. // 1、中序遍历左子树
    38. if (this.left != null) {
    39. this.left.middleOrder();
    40. }
    41. // 2、输出结点
    42. System.out.printf("%s ", this.value);
    43. // 3、中序遍历右子树
    44. if (this.right != null) {
    45. this.right.middleOrder();
    46. }
    47. }
    48. /**
    49. * 插入结点
    50. */
    51. public void addNode(TreeNode node) {
    52. // 插入结点小于当前结点,则往当前结点左子结点进行插入
    53. if (node.value < this.value) {
    54. if (this.left == null) {
    55. // 左子结点为空时,则直接插入
    56. this.left = node;
    57. } else {
    58. // 左子结点不为空时,则往左子结点插入
    59. this.left.addNode(node);
    60. }
    61. // 否则往当前结点右子结点进行插入
    62. } else {
    63. if (this.right == null) {
    64. // 右子结点为空时,则直接插入
    65. this.right = node;
    66. } else {
    67. // 右子结点不为空时,则往右子结点插入
    68. this.right.addNode(node);
    69. }
    70. }
    71. }
    72. /**
    73. * 查找结点
    74. */
    75. public TreeNode searchNode(TreeNode node) {
    76. // 查找结点的值等于当前结点
    77. if (node.value == this.value) {
    78. return this;
    79. } else if (node.value < this.value ) {
    80. //查找结点的值小于当前结点,继续从当前结点的左子结点查找
    81. if (this.left != null) {
    82. return this.left.searchNode(node);
    83. }
    84. } else {
    85. //查找结点的值小于当前结点,继续从当前结点的左子结点查找
    86. if (this.right != null) {
    87. return this.right.searchNode(node);
    88. }
    89. }
    90. return null;
    91. }
    92. /**
    93. * 查找父结点
    94. */
    95. public TreeNode searchParentNode(TreeNode node) {
    96. // 如果当前结点就是要查找结点的父结点,直接返回
    97. if ((this.left != null && this.left.value == node.value)
    98. || (this.right != null && this.right.value == node.value)) {
    99. return this;
    100. // 如果查找结点小于当前结点的左结点,则往左子结点递归查找
    101. } else if (this.left != null && node.value < this.left.value) {
    102. return this.left.searchParentNode(node);
    103. // 如果查找结点大于当前结点的右结点,则往右子结点递归查找
    104. } else if (this.right != null && node.value > this.right.value){
    105. return this.right.searchParentNode(node);
    106. }
    107. return null;
    108. }
    109. }
    110. /**
    111. * 中序遍历
    112. */
    113. public void middleOrderPrint() {
    114. if (rootNode == null) {
    115. return;
    116. }
    117. rootNode.middleOrder();
    118. }
    119. /**
    120. * 插入结点
    121. */
    122. public void add(int value) {
    123. TreeNode node = new TreeNode(value);
    124. // 根结点为空时,则插入结点直接当作根结点
    125. if (rootNode == null) {
    126. rootNode = node;
    127. } else {
    128. rootNode.addNode(node);
    129. }
    130. }
    131. /**
    132. * 查找结点
    133. */
    134. public boolean search(int value) {
    135. TreeNode treeNode = searchNode(value);
    136. return treeNode != null ? true : false;
    137. }
    138. /**
    139. * 查找结点
    140. */
    141. private TreeNode searchNode(int value) {
    142. TreeNode node = new TreeNode(value);
    143. // 根结点为空时,直接返回
    144. if (rootNode == null) {
    145. return null;
    146. }
    147. return rootNode.searchNode(node);
    148. }
    149. /**
    150. * 查找父结点
    151. */
    152. private TreeNode searchParentNode(int value) {
    153. TreeNode node = new TreeNode(value);
    154. // 根结点为空或者要查找的结点就是根结点时,直接返回
    155. if (rootNode == null || rootNode.value == value) {
    156. return null;
    157. }
    158. return rootNode.searchParentNode(node);
    159. }
    160. /**
    161. * 删除指定结点下最小结点的值
    162. * 1. 返回的是以node为根节点的二叉排序树的最小节点的值
    163. * 2. 删除以node为根节点的二叉排序树的最小节点
    164. */
    165. private int delTreeMin(TreeNode node) {
    166. TreeNode target = node;
    167. // 循环的查找左节点,就会找到最小值
    168. while (target.left != null) {
    169. target = target.left;
    170. }
    171. // 这时target就指向了最小节点
    172. // 删除最小节点
    173. delete(target.value);
    174. return target.value;
    175. }
    176. /**
    177. * 删除结点
    178. */
    179. public void delete(int value) {
    180. // 根结点为空时,直接返回
    181. if (rootNode == null) {
    182. return;
    183. }
    184. // 1、需要先去找到要删除的节点targetNode,没有找到直接返回
    185. TreeNode targetNode = searchNode(value);
    186. if (targetNode == null) {
    187. return;
    188. }
    189. // 2、如果我们发现当前这颗二叉排序树删除的点就是根结点,且只有一个节点
    190. if (rootNode.left == null && rootNode.right == null) {
    191. rootNode = null;
    192. return;
    193. }
    194. // 3、去找到targetNode的父节点
    195. TreeNode parentNode = searchParentNode(value);
    196. // (1) 如果要删除的节点是叶子节点
    197. if (targetNode.left == null && targetNode.right == null) {
    198. // 判断targetNode是父节点的左子节点还是右子节点
    199. if (parentNode != null && parentNode.left != null && parentNode.left.value == value) {
    200. parentNode.left = null;
    201. } else if (parentNode != null && parentNode.right != null && parentNode.right.value == value) {
    202. parentNode.right = null;
    203. }
    204. // (2) 删除有两棵子树的节点
    205. } else if (targetNode.left != null && targetNode.right != null) {
    206. // 从targetNode的右子树中,找到最小的节点,先删除这个最小结点,然后把最小结点的值保存到targetNode中
    207. int minVal = delTreeMin(targetNode.right);
    208. targetNode.value = minVal;
    209. // (3) 删除只有一棵子树的节点
    210. } else {
    211. // 如果要删除的节点有左子节点
    212. if (targetNode.left != null) {
    213. if (parentNode != null) {
    214. // 判断targetNode是父节点的左子节点还是右子节点
    215. if (parentNode.left.value == value) {
    216. parentNode.left = targetNode.left;
    217. } else {
    218. parentNode.right = targetNode.left;
    219. }
    220. } else {
    221. // 表示删除的是根结点
    222. rootNode = targetNode.left;
    223. }
    224. // 如果要删除的节点有右子节点
    225. } else {
    226. if (parentNode != null) {
    227. // 判断targetNode是父节点的左子节点还是右子节点
    228. if (parentNode.left.value == value) {
    229. parentNode.left = targetNode.right;
    230. } else {
    231. parentNode.right = targetNode.right;
    232. }
    233. } else {
    234. // 表示删除的是根结点
    235. rootNode = targetNode.right;
    236. }
    237. }
    238. }
    239. }
    240. public static void main(String[] args) {
    241. // 61 87 55 42 58
    242. BinarySortTree binarySortTree = new BinarySortTree();
    243. Scanner scanner = new Scanner(System.in);
    244. boolean loop = true;
    245. while (loop) {
    246. System.out.print("【二叉排序树】插入(1)、查找(2)、删除(3)、遍历(4)、退出(0):");
    247. Integer key = scanner.nextInt();
    248. switch (key) {
    249. case 1:
    250. System.out.print("请输入插入值:");
    251. int value = scanner.nextInt();
    252. binarySortTree.add(value);
    253. break;
    254. case 2:
    255. System.out.print("请输入查找值:");
    256. int value2 = scanner.nextInt();
    257. System.out.println("查找结果:" + binarySortTree.search(value2));
    258. break;
    259. case 3:
    260. System.out.print("请输入删除值:");
    261. int value3 = scanner.nextInt();
    262. binarySortTree.delete(value3);
    263. break;
    264. case 4:
    265. binarySortTree.middleOrderPrint();
    266. System.out.println();
    267. break;
    268. case 0:
    269. scanner.close();
    270. loop = false;
    271. break;
    272. default: break;
    273. }
    274. }
    275. System.out.println("程序退出。。。");
    276. }
    277. }