1. 思路
1.1 遍历思路
(1)前序
- 打印当前节点数值
- 若左树非空,递归左树
- 若右树非空,递归右树
(2)中序
- 若左树非空,递归左树
- 打印当前节点数值
- 若右树非空,递归右树
(3)后序
- 若左树非空,递归左树
- 若右树非空,递归右树
- 打印当前节点数值
1.2 查找思路
(1)前序
- 检查当前节点值,若与输入值相等,则返回当前节点
- 设置临时节点变量node,用于储存找到的节点(初始化为null)
- 查询左树
- 若左树非空,递归左树,并将返回结果赋值给临时变量node
- 递归完成,若node非null,说明找到,返回node
- 查询右树
- 若右树非空,递归右树,并将返回结果赋值给临时变量node
- 返回node(若node非空,则找到;否则未找到,返回null)
(2)中序
- 设置临时节点变量node,用于储存找到的节点(初始化为null)
- 查询左树
- 若左树非空,递归左树,并将返回结果赋值给临时变量node
- 递归完成,若node非null,说明找到,返回node
- 检查当前节点值,若与输入值相等,则返回当前节点
- 查询右树
- 若右树非空,递归右树,并将返回结果赋值给临时变量node
- 返回node(若node非空,则找到;否则未找到,返回null)
(3)后序
- 设置临时节点变量node,用于储存找到的节点(初始化为null)
- 查询左树:
- 若左树非空,递归左树,并将返回结果赋值给临时变量node
- 递归完成,若node非null,说明找到,返回node
- 查询右树
- 若右树非空,递归右树,并将返回结果赋值给临时变量node
- 返回node(若node非空,则找到;否则未找到,返回null)
- 检查当前节点
- 检查当前节点值,若与输入值相等,则返回当前节点
- 否则,返回null
2. 基本结构
2.1 TreeNode (二叉树节点)
-
int index;
-
TreeNode leftNode;
-
TreeNode rightNode;
-
preOrderTraversal()
-
infixOrderTraversal()
-
postOrderTraversal()
-
preOrderSearch()
-
infixOrderSearch()
-
postOrderSearch()
2.2 BinaryTree(二叉树)
- TreeNode rootNode;
// 一下方法调用TreeNode内的相应方法实现查找或遍历 - preOrderTraversal()
- infixOrderTraversal()
- postOrderTraversal()
- preOrderSearch()
- infixOrderSearch()
- postOrderSearch()
3. 代码实现
public class BinaryTree {
private TreeNode rootNode;
// for test
public static ArrayList<Integer> orderList = new ArrayList<>();
// getter and setter
public TreeNode getRootNode() {
return rootNode;
}
public void setRootNode(TreeNode rootNode) {
this.rootNode = rootNode;
}
/**
* 前序遍历
*/
public void preOrderTraversal() {
if (this.rootNode == null) {
throw new RuntimeException("empty");
} else {
this.rootNode.preOrderTraversal();
}
}
/**
* 中序遍历
*/
public void infixOrderTraversal() {
if (this.rootNode == null) {
throw new RuntimeException("empty");
} else {
this.rootNode.infixOrderTraversal();
}
}
/**
* 后序遍历
*/
public void postOrderTraversal() {
if (this.rootNode == null) {
throw new RuntimeException("empty");
} else {
this.rootNode.postOrderTraversal();
}
}
/**
* 前序查找
* @param searchIndex - 要查找的节点权重
* @return - 找到则返回节点,未找到则返回null
*/
public TreeNode preOrderSearch(int searchIndex) {
if (this.rootNode == null) {
throw new RuntimeException("empty");
}
return this.rootNode.preOrderSearch(searchIndex);
}
/**
* 中序查找
* @param searchIndex - 要查找的节点权重
* @return - 找到则返回节点,未找到则返回null
*/
public TreeNode infixOrderSearch(int searchIndex) {
if (this.rootNode == null) {
throw new RuntimeException("empty");
}
return this.rootNode.infixOrderSearch(searchIndex);
}
/**
* 后序查找
* @param searchIndex - 要查找的节点权重
* @return - 找到则返回节点,未找到则返回null
*/
public TreeNode postOrderSearch(int searchIndex) {
if (this.rootNode == null) {
throw new RuntimeException("empty");
}
return this.rootNode.postOrderSearch(searchIndex);
}
/**
* 牛客网算法题:按照层次打印这棵二叉树。
*
* 给定二叉树的根结点root,请返回打印结果,结果按照每一层一个数组进行储存,
* 所有数组的顺序按照层数从上往下,且每一层的数组内元素按照从左往右排列。保证结点数小于等于500。
* @param root - 根节点
* @return - 二维数组,每个数组储存的是每层数据的数组
*/
public int[][] printTree(TreeNode root) {
// 0. check root
if (root == null) {
return null;
}
ArrayList<ArrayList<TreeNode>> arrayList = new ArrayList<>();
boolean hasNextLevel = true;
TreeNode currentNode = root;
while (hasNextLevel) {
ArrayList<TreeNode> currentLevelNodeList = new ArrayList<>();
// if it's the first level
if (arrayList.isEmpty()) {
currentLevelNodeList.add(root);
if (root.getLeftNode() == null && root.getRightNode() == null) {
hasNextLevel = false;
}
}
// not the first level
else {
// add current level node list into the arrayList and check next level
hasNextLevel = false;
for (TreeNode node : arrayList.get(arrayList.size() - 1)) {
if (node.getLeftNode() != null) {
currentLevelNodeList.add(node.getLeftNode());
if (node.getLeftNode().getLeftNode() != null || node.getLeftNode().getRightNode() != null) {
hasNextLevel = true;
}
}
if (node.getRightNode() != null) {
currentLevelNodeList.add(node.getRightNode());
if (node.getRightNode().getLeftNode() != null || node.getRightNode().getRightNode() != null) {
hasNextLevel = true;
}
}
}
}
arrayList.add(currentLevelNodeList);
}
int[][] finalArray = new int[arrayList.size()][];
for (int i = 0; i < arrayList.size(); i++) {
ArrayList<TreeNode> currentList = arrayList.get(i);
int[] currentArray = new int[currentList.size()];
for (int j = 0; j < currentList.size(); j++) {
currentArray[j] = currentList.get(j).getIndex();
}
finalArray[i] = currentArray;
}
return finalArray;
}
}
class TreeNode {
private int index;
private TreeNode leftNode;
private TreeNode rightNode;
public TreeNode(int index) {
this.index = index;
}
/**
* 前序遍历
* 1. 打印当前节点数值
* 2. 若左树非空,递归左树
* 3. 若右树非空,递归右树
*/
public void preOrderTraversal() {
// 1. 打印当前节点数值
BinaryTree.orderList.add(this.index);
System.out.print(this.index + " ");
// 2. 若左树非空,递归左树
if (this.leftNode != null) {
this.leftNode.preOrderTraversal();
}
// 3. 若右树非空,递归右树
if (this.rightNode != null){
this.rightNode.preOrderTraversal();
}
}
/**
* 中序遍历
* 1. 若左树非空,递归左树
* 2. 打印当前节点数值
* 3. 若右树非空,递归右树
*/
public void infixOrderTraversal() {
// 1. 若左树非空,递归左树
if (this.leftNode != null) {
this.leftNode.infixOrderTraversal();
}
// 2. 打印当前节点数值
BinaryTree.orderList.add(this.index);
System.out.print(this.index + " ");
// 3. 若右树非空,递归右树
if (this.rightNode != null) {
this.rightNode.infixOrderTraversal();
}
}
/**
* 后序遍历
* 1. 若左树非空,递归左树
* 2. 若右树非空,递归右树
* 3. 打印当前节点数值
*/
public void postOrderTraversal() {
// 1. 若左树非空,递归左树
if (this.leftNode != null) {
this.leftNode.postOrderTraversal();
}
// 2. 若右树非空,递归右树
if (this.rightNode != null) {
this.rightNode.postOrderTraversal();
}
BinaryTree.orderList.add(this.index);
// 3. 打印当前节点数值
System.out.print(this.index + " ");
}
/**
* 前序查找
* 1. 检查当前节点值,若与输入值相等,则返回当前节点
* 2. 设置临时节点变量node,用于储存找到的节点(初始化为null)
* 3. 查询左树
* 3.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
* 3.2 递归完成,若node非null,说明找到,返回node
* 4. 查询右树
* 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
* 4.2 返回node(若node非空,则找到;否则未找到,返回null)
*
* @param searchIndex - 要查找的节点权重
* @return - 找到则返回节点,未找到则返回null
*/
public TreeNode preOrderSearch(int searchIndex) {
// 1. 检查当前节点值,若与输入值相等,则返回当前节点
if (this.index == searchIndex) {
return this;
}
// 2. 设置临时节点变量node,用于储存找到的节点(初始化为null)
TreeNode node = null;
// 3. 查询左树
// 3.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
if (this.leftNode != null) {
node = this.leftNode.preOrderSearch(searchIndex);
}
// 3.2 递归完成,若node非null,说明找到,返回node
if (node != null) {
return node;
}
// 4. 查询右树
// 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
if (this.rightNode != null) {
node = this.rightNode.preOrderSearch(searchIndex);
}
// 4.2 返回node(若node非空,则找到;否则未找到,返回null)
return node;
}
/**
* 中序查找
* 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
* 2. 查询左树
* 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
* 2.2 递归完成,若node非null,说明找到,返回node
* 3. 检查当前节点值,若与输入值相等,则返回当前节点
* 4. 查询右树
* 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
* 4.2 返回node(若node非空,则找到;否则未找到,返回null)
*
* @param searchIndex - 要查找的节点权重
* @return - 找到则返回节点,未找到则返回null
*/
public TreeNode infixOrderSearch(int searchIndex) {
// 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
TreeNode node = null;
// 2. 查询左树
// 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
if (this.leftNode != null) {
node = this.leftNode.infixOrderSearch(searchIndex);
}
// 2.2 递归完成,若node非null,说明找到,返回node
if (node != null) {
return node;
}
// 3. 检查当前节点值,若与输入值相等,则返回当前节点
if (this.index == searchIndex) {
return this;
}
// 4. 查询右树
// 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
if (this.rightNode != null) {
node = this.rightNode.infixOrderSearch(searchIndex);
}
// 4.2 返回node(若node非空,则找到;否则未找到,返回null)
return node;
}
/**
* 后序查找
* 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
* 2. 查询左树:
* 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
* 2.2 递归完成,若node非null,说明找到,返回node
* 3. 查询右树
* 3.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
* 3.2 返回node(若node非空,则找到;否则未找到,返回null)
* 4. 检查当前节点
* 4.1 检查当前节点值,若与输入值相等,则返回当前节点
* 4.2 否则,返回null
*
* @param searchIndex - 要查找的节点权重
* @return - 找到则返回节点,未找到则返回null
*/
public TreeNode postOrderSearch(int searchIndex) {
// 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
TreeNode node = null;
// 2. 查询左树:
// 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
if (this.leftNode != null) {
node = this.leftNode.postOrderSearch(searchIndex);
}
// 2.2 递归完成,若node非null,说明找到,返回node
if (node != null) {
return node;
}
// 3. 查询右树
// 3.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
if (this.rightNode != null) {
node = this.rightNode.postOrderSearch(searchIndex);
}
// 3.2 递归完成,若node非null,说明找到,返回node
if (node != null) {
return node;
}
// 4. 检查当前节点
// 4.1 检查当前节点值,若与输入值相等,则返回当前节点
if (this.index == searchIndex) {
return this;
}
// 4.2 否则,返回null
return null;
}
@Override
public String toString() {
return "TreeNode{" +
"index=" + index +
'}';
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public TreeNode getLeftNode() {
return leftNode;
}
public void setLeftNode(TreeNode leftNode) {
this.leftNode = leftNode;
}
public TreeNode getRightNode() {
return rightNode;
}
public void setRightNode(TreeNode rightNode) {
this.rightNode = rightNode;
}
}