Java中树和树的几种常规遍历方法
Posted 闲情偶寄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中树和树的几种常规遍历方法相关的知识,希望对你有一定的参考价值。
其中包含有先序遍历、中序遍历、后序遍历以及广度优先遍历四种遍历树的方法:
1 package com.ietree.basic.datastructure.tree.binarytree; 2 3 import java.util.ArrayDeque; 4 import java.util.ArrayList; 5 import java.util.List; 6 import java.util.Queue; 7 8 /** 9 * Created by ietree 10 * 2017/5/1 11 */ 12 public class ThreeLinkBinTree<E> { 13 14 public static class TreeNode { 15 16 Object data; 17 TreeNode left; 18 TreeNode right; 19 TreeNode parent; 20 21 public TreeNode() { 22 23 } 24 25 public TreeNode(Object data) { 26 this.data = data; 27 } 28 29 public TreeNode(Object data, TreeNode left, TreeNode right, TreeNode parent) { 30 this.data = data; 31 this.left = left; 32 this.right = right; 33 this.parent = parent; 34 } 35 36 } 37 38 private TreeNode root; 39 40 // 以默认的构造器创建二叉树 41 public ThreeLinkBinTree() { 42 this.root = new TreeNode(); 43 } 44 45 // 以指定根元素创建二叉树 46 public ThreeLinkBinTree(E data) { 47 this.root = new TreeNode(data); 48 } 49 50 /** 51 * 为指定节点添加子节点 52 * 53 * @param parent 需要添加子节点的父节点的索引 54 * @param data 新子节点的数据 55 * @param isLeft 是否为左节点 56 * @return 新增的节点 57 */ 58 public TreeNode addNode(TreeNode parent, E data, boolean isLeft) { 59 60 if (parent == null) { 61 throw new RuntimeException(parent + "节点为null, 无法添加子节点"); 62 } 63 if (isLeft && parent.left != null) { 64 throw new RuntimeException(parent + "节点已有左子节点,无法添加左子节点"); 65 } 66 if (!isLeft && parent.right != null) { 67 throw new RuntimeException(parent + "节点已有右子节点,无法添加右子节点"); 68 } 69 70 TreeNode newNode = new TreeNode(data); 71 if (isLeft) { 72 // 让父节点的left引用指向新节点 73 parent.left = newNode; 74 } else { 75 // 让父节点的left引用指向新节点 76 parent.right = newNode; 77 } 78 // 让新节点的parent引用到parent节点 79 newNode.parent = parent; 80 return newNode; 81 } 82 83 // 判断二叉树是否为空 84 public boolean empty() { 85 // 根据元素判断二叉树是否为空 86 return root.data == null; 87 } 88 89 // 返回根节点 90 public TreeNode root() { 91 if (empty()) { 92 throw new RuntimeException("树为空,无法访问根节点"); 93 } 94 return root; 95 } 96 97 // 返回指定节点(非根节点)的父节点 98 public E parent(TreeNode node) { 99 if (node == null) { 100 throw new RuntimeException("节点为null,无法访问其父节点"); 101 } 102 return (E) node.parent.data; 103 } 104 105 // 返回指定节点(非叶子)的左子节点,当左子节点不存在时返回null 106 public E leftChild(TreeNode parent) { 107 if (parent == null) { 108 throw new RuntimeException(parent + "节点为null,无法添加子节点"); 109 } 110 return parent.left == null ? null : (E) parent.left.data; 111 } 112 113 // 返回指定节点(非叶子)的右子节点,当右子节点不存在时返回null 114 public E rightChild(TreeNode parent) { 115 if (parent == null) { 116 throw new RuntimeException(parent + "节点为null,无法添加子节点"); 117 } 118 return parent.right == null ? null : (E) parent.right.data; 119 } 120 121 // 返回该二叉树的深度 122 public int deep() { 123 // 获取该树的深度 124 return deep(root); 125 } 126 127 // 这是一个递归方法:每一棵子树的深度为其所有子树的最大深度 + 1 128 private int deep(TreeNode node) { 129 if (node == null) { 130 return 0; 131 } 132 // 没有子树 133 if (node.left == null && node.right == null) { 134 return 1; 135 } else { 136 int leftDeep = deep(node.left); 137 int rightDeep = deep(node.right); 138 // 记录其所有左、右子树中较大的深度 139 int max = leftDeep > rightDeep ? leftDeep : rightDeep; 140 // 返回其左右子树中较大的深度 + 1 141 return max + 1; 142 } 143 } 144 145 // 实现先序遍历 146 // 1、访问根节点 147 // 2、递归遍历左子树 148 // 3、递归遍历右子树 149 public List<TreeNode> preIterator() { 150 return preIterator(root); 151 } 152 153 private List<TreeNode> preIterator(TreeNode node) { 154 155 List<TreeNode> list = new ArrayList<TreeNode>(); 156 // 处理根节点 157 list.add(node); 158 159 // 递归处理左子树 160 if (node.left != null) { 161 list.addAll(preIterator(node.left)); 162 } 163 164 // 递归处理右子树 165 if (node.right != null) { 166 list.addAll(preIterator(node.right)); 167 } 168 169 return list; 170 171 } 172 173 // 实现中序遍历 174 // 1、递归遍历左子树 175 // 2、访问根节点 176 // 3、递归遍历右子树 177 public List<TreeNode> inIterator() { 178 return inIterator(root); 179 } 180 181 private List<TreeNode> inIterator(TreeNode node) { 182 183 List<TreeNode> list = new ArrayList<TreeNode>(); 184 185 // 递归处理左子树 186 if (node.left != null) { 187 list.addAll(inIterator(node.left)); 188 } 189 190 // 处理根节点 191 list.add(node); 192 193 // 递归处理右子树 194 if (node.right != null) { 195 list.addAll(inIterator(node.right)); 196 } 197 198 return list; 199 200 } 201 202 // 实现后序遍历 203 // 1、递归遍历左子树 204 // 2、递归遍历右子树 205 // 3、访问根节点 206 public List<TreeNode> postIterator() { 207 return postIterator(root); 208 } 209 210 private List<TreeNode> postIterator(TreeNode node) { 211 212 List<TreeNode> list = new ArrayList<TreeNode>(); 213 214 // 递归处理左子树 215 if (node.left != null) { 216 list.addAll(postIterator(node.left)); 217 } 218 219 // 递归处理右子树 220 if (node.right != null) { 221 list.addAll(postIterator(node.right)); 222 } 223 224 // 处理根节点 225 list.add(node); 226 227 return list; 228 229 } 230 231 // 实现广度优先遍历 232 // 广度优先遍历又称为按层遍历,整个遍历算法先遍历二叉树的第一层(根节点),再遍历根节点的两个子节点(第二层),以此类推 233 public List<TreeNode> breadthFirst() { 234 235 Queue<TreeNode> queue = new ArrayDeque<TreeNode>(); 236 List<TreeNode> list = new ArrayList<TreeNode>(); 237 if (root != null) { 238 // 将根元素加入“队列” 239 queue.offer(root); 240 } 241 while (!queue.isEmpty()) { 242 // 将该队列的“队尾”的元素添加到List中 243 list.add(queue.peek()); 244 TreeNode p = queue.poll(); 245 // 如果左子节点不为null,将它加入“队列” 246 if (p.left != null) { 247 queue.offer(p.left); 248 } 249 // 如果右子节点不为null,将它加入“队列” 250 if (p.right != null) { 251 queue.offer(p.right); 252 } 253 } 254 return list; 255 } 256 257 }
以上是关于Java中树和树的几种常规遍历方法的主要内容,如果未能解决你的问题,请参考以下文章