本文總結了常見高頻的關於二叉樹的算法考察。
1.計算一個給定二叉樹的葉子節點數目。
可以采用遞歸的方式進行累加
public static int calculateTreeNodeNumber(TreeNode treeNode) {
if (treeNode == null) {
return 0;
}
return calculateTreeNodeNumber(treeNode.left) + calculateTreeNodeNumber(treeNode.right) + 1;
}
2.計算二叉樹的深度。
跟上題一樣采用遞歸的方式,但需返回左右子樹中較深的深度。
public static int getTreeDepth(TreeNode tree) {
if (tree == null) {
return 0;
}
int left = getTreeDepth(tree.left);
int right = getTreeDepth(tree.right);
return left >= right ? left + 1 : right + 1;
}
3.如何打印二叉樹每層的節點。
借助一個隊列,先把根節點入隊,每打印一個節點的值時,也就是打印隊列頭的節點時,都會把它的的左右孩子入隊,並且把該節點出隊。直到隊列為空。
public static void printByLevel(TreeNode tree) {
if (tree == null) {
return;
}
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(tree);
while (!queue.isEmpty()) {
TreeNode pop = queue.pop();
System.out.println(pop.val);
if (pop.left != null) {
queue.add(pop.left);
}
if (pop.right != null) {
queue.add(pop.right);
}
}
}
4.二叉樹的Z型遍歷。
借助兩個隊列,一個正序打印,一個逆序打印。
public static void printByZ(TreeNode tree) {
if (tree == null) {
return;
}
List<TreeNode> orderQueue = new ArrayList<>();
List<TreeNode> disorderQueue = new ArrayList<>();
orderQueue.add(tree);
while (!orderQueue.isEmpty()|| !disorderQueue.isEmpty()) {
if (!orderQueue.isEmpty()) {
for (int i = 0; i < orderQueue.size(); i++) {
TreeNode leaf = orderQueue.get(i);
if (leaf.left != null) {
disorderQueue.add(leaf.left);
}
if (leaf.right != null) {
disorderQueue.add(leaf.right);
}
}
for (TreeNode node : orderQueue) {
System.out.println(node.val);
}
orderQueue.clear();
}
if (!disorderQueue.isEmpty()) {
for (int i = 0; i < disorderQueue.size(); i++) {
TreeNode leaf = disorderQueue.get(i);
if (leaf.left != null) {
orderQueue.add(leaf.left);
}
if (leaf.right != null) {
orderQueue.add(leaf.right);
}
}
for (int i = disorderQueue.size()-1; i >=0 ; i--) {
TreeNode leaf = disorderQueue.get(i);
System.out.println(leaf.val);
}
disorderQueue.clear();
}
}
}
5.一個已經構建好的TreeSet,怎么完成倒排序。
遞歸更換左右子樹即可
public static void reverse(TreeNode tree) {
if (tree.left == null && tree.right == null) {
return;
}
TreeNode tmp = tree.right;
tree.right = tree.left;
tree.left = tmp;
reverse(tree.left);
reverse(tree.right);
}
6.二叉樹的前序遍歷。
前序遞歸
public static void preOrderRecursion(TreeNode tree) {
if (tree != null) {
System.out.print(tree.val + "->");
preOrderRecursion(tree.left);
preOrderRecursion(tree.right);
}
}
前序非遞歸
public static void preOrderNonRecursion(TreeNode tree) {
Stack<TreeNode> stack = new Stack<>();
TreeNode node = tree;
while (node != null || !stack.empty()) {
if (node != null) {
System.out.print(node.val + "->");
stack.push(node);
node = node.left;
} else {
TreeNode tem = stack.pop();
node = tem.right;
}
}
}
7.二叉樹的中序遍歷。
中序遞歸
public static void middleOrderRecursion(TreeNode tree) {
if (tree != null) {
middleOrderRecursion(tree.left);
System.out.print(tree.val + "->");
middleOrderRecursion(tree.right);
}
}
中序非遞歸
public static void middleOrderNonRecursion(TreeNode tree) {
Stack<TreeNode> stack = new Stack<>();
TreeNode node = tree;
while (node != null || !stack.isEmpty()) {
if (node != null) {
stack.push(node);
node = node.left;
} else {
TreeNode tem = stack.pop();
System.out.print(tem.val + "->");
node = tem.right;
}
}
}
8.二叉樹的后序遍歷。
后序遞歸
public static void postOrderTraverseRecursion(TreeNode root) {
if (root != null) {
postOrderTraverseRecursion(root.left);
postOrderTraverseRecursion(root.right);
System.out.print(root.val + "->");
}
}
后序非遞歸
public static void postOrderTraverseNonRecursion1(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<>();
LinkedList<TreeNode> output = new LinkedList<>();
if (root == null) {
return;
}
stack.add(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pollLast();
output.addFirst(node);
if (node.left != null) {
stack.add(node.left);
}
if (node.right != null) {
stack.add(node.right);
}
}
for (TreeNode node : output) {
System.out.print(node.val + "->");
}
}
筆者個人總結,如有錯誤之處望不吝指出。
本文轉自我的個人博客:《CoderV的進階筆記》
歡迎加入Java后端架構技術討論群:1398880
我的公眾號:CoderV的進階筆記,記錄技術心得