1、二叉树

树有很多种,每个结点最多只能有两个子结点的成为二叉树,二叉树的结点分为左结点和右结点。

二叉树遍历:
1、前序遍历:从二叉树的根结点出发,当第一次到达结点时就输出结点数据,按照先向左在向右的方向访问。
2、中序遍历:从二叉树的根结点出发,当第二次到达结点时就输出结点数据,按照先向左在向右的方向访问。
3、后序遍历:从二叉树的根结点出发,当第三次到达结点时就输出结点数据,按照先向左在向右的方向访问。
4、层序遍历:层次遍历就是按照树的层次自上而下的遍历二叉树**

  1. /**
  2. * 二叉树遍历:
  3. */
  4. public class BinaryTree {
  5. /**
  6. * 根结点
  7. */
  8. private TreeNode rootNode;
  9. /**
  10. * 结点类
  11. */
  12. private class TreeNode {
  13. private String name;
  14. private TreeNode left;
  15. private TreeNode right;
  16. public TreeNode(String name, TreeNode left, TreeNode right) {
  17. this.name = name;
  18. this.left = left;
  19. this.right = right;
  20. }
  21. /**
  22. * 前序遍历
  23. */
  24. public void beforeOrder() {
  25. if (this == null) {
  26. return;
  27. }
  28. // 1、输出结点
  29. System.out.printf("%s ", this.name);
  30. // 2、前序遍历左子树
  31. if (this.left != null) {
  32. this.left.beforeOrder();
  33. }
  34. // 3、前序遍历右子树
  35. if (this.right != null) {
  36. this.right.beforeOrder();
  37. }
  38. }
  39. /**
  40. * 中序遍历
  41. */
  42. public void middleOrder() {
  43. if (this == null) {
  44. return;
  45. }
  46. // 1、中序遍历左子树
  47. if (this.left != null) {
  48. this.left.middleOrder();
  49. }
  50. // 2、输出结点
  51. System.out.printf("%s ", this.name);
  52. // 3、中序遍历右子树
  53. if (this.right != null) {
  54. this.right.middleOrder();
  55. }
  56. }
  57. /**
  58. * 后序遍历
  59. */
  60. public void afterOrder() {
  61. if (this == null) {
  62. return;
  63. }
  64. // 1、后序遍历左子树
  65. if (this.left != null) {
  66. this.left.afterOrder();
  67. }
  68. // 2、后序遍历右子树
  69. if (this.right != null) {
  70. this.right.afterOrder();
  71. }
  72. // 3、输出结点
  73. System.out.printf("%s ", this.name);
  74. }
  75. /**
  76. * 查找结点(前序遍历)
  77. */
  78. public boolean beforeOrderSearch(TreeNode node) {
  79. if (this == null) {
  80. return false;
  81. }
  82. // 1、比较查找值跟当前结点是否相等,如果相等则直接返回
  83. if (Objects.equals(node.name, this.name)) {
  84. return true;
  85. }
  86. // 2、当前结点没找到的话,则继续从左子树去查找
  87. boolean bool = false;
  88. if (this.left != null) {
  89. bool = this.left.beforeOrderSearch(node);
  90. }
  91. // 3、左子树没找到的话,则继续从右子树去查找
  92. if (!bool) {
  93. if (this.right != null) {
  94. bool = this.right.beforeOrderSearch(node);
  95. }
  96. }
  97. return bool;
  98. }
  99. /**
  100. * 删除结点
  101. */
  102. public void deleteNode(TreeNode node){
  103. // 由于结点是单向的,根据父结点可以找到子结点,而子结点找不到父结点,所以需要判断子结点是不是要删除的结点
  104. if (this == null) {
  105. return;
  106. }
  107. // 1、如果左结点就是删除结点,则将左结点设为null,直接返回
  108. if (this.left != null && Objects.equals(this.left.name, node.name)) {
  109. this.left = null;
  110. return;
  111. }
  112. // 2、如果右结点就是删除结点,则将右结点设为null,直接返回
  113. if (this.right != null && Objects.equals(this.right.name, node.name)) {
  114. this.right = null;
  115. return;
  116. }
  117. // 3、找不到删除结点,则分别向左右结点递归
  118. this.left.deleteNode(node);
  119. this.right.deleteNode(node);
  120. }
  121. }
  122. public BinaryTree() {
  123. // 初始化二叉树
  124. // A
  125. // / \
  126. // B C
  127. // / \
  128. // D E
  129. TreeNode E = new TreeNode("E", null, null);
  130. TreeNode D = new TreeNode("D", null, null);
  131. TreeNode B = new TreeNode("B", D, E);
  132. TreeNode C = new TreeNode("C", null, null);
  133. this.rootNode = new TreeNode("A", B, C);
  134. }
  135. /**
  136. * 前序遍历
  137. */
  138. public void beforeOrderPrint() {
  139. if (rootNode == null) {
  140. System.out.println("前序遍历为空");
  141. return;
  142. }
  143. rootNode.beforeOrder();
  144. }
  145. /**
  146. * 中序遍历
  147. */
  148. public void middleOrderPrint() {
  149. if (rootNode == null) {
  150. System.out.println("中序遍历为空");
  151. return;
  152. }
  153. rootNode.middleOrder();
  154. }
  155. /**
  156. * 后序遍历
  157. */
  158. public void afterOrderPrint() {
  159. if (rootNode == null) {
  160. System.out.println("空树遍历为空");
  161. return;
  162. }
  163. rootNode.afterOrder();
  164. }
  165. /**
  166. * 查找(前序遍历)
  167. */
  168. public Boolean beforeOrderSearch(String name) {
  169. if (rootNode == null) {
  170. return false;
  171. }
  172. TreeNode node = new TreeNode(name, null, null);
  173. return rootNode.beforeOrderSearch(node);
  174. }
  175. /**
  176. * 删除结点
  177. */
  178. public void deleteNode(String name){
  179. if (rootNode == null) {
  180. System.out.println("二叉树为空,无法删除");
  181. return;
  182. }
  183. // 删除根结点时,则直接将根结点设为null
  184. if (Objects.equals(rootNode.name, name)) {
  185. rootNode = null;
  186. return;
  187. }
  188. TreeNode node = new TreeNode(name, null, null);
  189. rootNode.deleteNode(node);
  190. }
  191. public static void main(String[] args) {
  192. BinaryTree binaryTree = new BinaryTree();
  193. // A B D E C
  194. System.out.print("前序遍历:");
  195. binaryTree.beforeOrderPrint();
  196. System.out.println();
  197. // D B E A C
  198. System.out.print("中序遍历:");
  199. binaryTree.middleOrderPrint();
  200. System.out.println();
  201. // D E B C A
  202. System.out.print("后序遍历:");
  203. binaryTree.afterOrderPrint();
  204. System.out.println();
  205. System.out.println("查找(前序遍历):" + binaryTree.beforeOrderSearch("D"));
  206. binaryTree.deleteNode("C");
  207. System.out.print("删除结点后:");
  208. binaryTree.beforeOrderPrint();
  209. }
  210. }


二叉树存储方式:**
1、顺序存储
2、链式存储

/**
 * 《顺序存储二叉树》
 *      二叉树的顺序存储结构就是使用一维数组存储二叉树中的结点,并且结点的存储位置,就是数组的下标索引。
 *  从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换成树,树也可以转换成数组
 *
 *           A[0]
 *         /     \                           0  1  2  3  4  5  6
 *        B[1]   C[2]              ---->     |  |  |  |  |  |  |
 *      /   \    /   \                      [A, B, C, D, E, F, G]
 *    D[3] E[4] F[5] G[6]
 *
 * 顺序存储二叉树的特点:
 *   (1)顺序二叉树通常只考虑完全二叉树
 *   (2)第n个元素的左子节点为 2 * n + 1
 *   (3)第n个元素的右子节点为 2 * n + 2
 *   (4)第n个元素的父节点为 (n-1) / 2
 * n:表示二叉树中的第几个元素(按0开始编号如图所示)
 *
 */
public class ArrayBinaryTree {

    private String[] arr;

    public ArrayBinaryTree(String[] arr) {
        this.arr = arr;
    }

    /**
     * 前序遍历
     */
    public void beforeOrder() {
        this.beforeOrder(0);
    }

    private void beforeOrder(int index) {
        if (index >= arr.length) {
            return;
        }
        // 1、输出结点
        System.out.printf("%s ", arr[index]);
        // 2、前序遍历左结点
        beforeOrder(2 * index + 1);
        // 3、前序遍历右结点
        beforeOrder(2 * index + 2);
    }

    public static void main(String[] args) {
        String[] arr = new String[]{"A", "B", "C", "D", "E", "F", "G"};
        ArrayBinaryTree tree = new ArrayBinaryTree(arr);
        // A  B  D  E  C  F  G
        tree.beforeOrder();
    }
}

2、多叉树

在二叉树中,每个节点有数据项,最多有两个子节点。如果允许每个节点可以有更多的数据项和更多的子节点,就是多叉树(multiway tree)
树 - 图1