递归遍历
前序遍历
public void preOrder(TreeNode node){
if (node != null){
System.out.println(node.data);
preOrder(node.leftNode);
preOrder(node.RightNode);
}
}
中序遍历
public void midOrder(TreeNode node){
if (node != null){
midOrder(node.leftNode);
System.out.println(node.data);
midOrder(node.RightNode);
}
}
后序遍历
public void posOrder(TreeNode node){
if (node != null){
posOrder(node.leftNode);
posOrder(node.RightNode);
System.out.println(node.data);
}
}
非递归遍历
前序遍历
public void preOrder1(TreeNode node){
Stack<TreeNode> stack = new Stack<>();
while (node != null || !stack.empty()){
while (node != null){
System.out.println(node.data);
stack.push(node);
node = node.leftNode;
}
if (!stack.empty()){
node = stack.pop();
node = node.RightNode;
}
}
}
中序遍历
public void midOrder1(TreeNode node){
Stack<TreeNode> stack = new Stack<>();
while ( node != null || !stack.empty()){
while ( node != null){
stack.push(node);
node = node.leftNode;
}
if (!stack.empty()){
node = stack.pop();
System.out.println(node.data);
node = node.RightNode;
}
}
}
后序遍历
方法1:
public void posOrder1(TreeNode node){
Stack<TreeNode> stack1 = new Stack<>();
Stack<Integer> stack2 = new Stack<>();
while (node != null || !stack1.empty()){
while ( node != null){
stack1.push(node);
stack2.push(0);
node = node.leftNode;
}
while (!stack1.empty() && stack2.peek() == 1){
stack2.pop();
System.out.println(stack1.pop().data);
}
if (!stack1.empty()){
stack2.pop();
stack2.push(1);
node = stack1.peek();
node = node.RightNode;
}
}
}
方法2:
public ArrayList<Integer> posOrder2(TreeNode node){
ArrayList<Integer> list = new ArrayList<>();
if (node != null){
Stack<TreeNode> stack = new Stack<>();
stack.push(node);
while (!stack.empty()){
TreeNode node1 = stack.pop();
list.add(node1.data);
if (node1.leftNode != null) stack.push(node1.leftNode);
if (node1.RightNode != null)stack.push(node1.RightNode);
}
Collections.reverse(list);
}
return list;
}
层序遍历
public void levelOrder1(TreeNode node){
if (node == null) return;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(node);
TreeNode node1;
while (!queue.isEmpty()){
node1 = queue.poll();
System.out.println(node1.data);
if (node1.leftNode != null)queue.offer(node1.leftNode);
if (node1.RightNode != null)queue.offer(node1.RightNode);
}
}
常见应用
二叉树的最大深度
public int depth(TreeNode node){
if (node == null) return 0;
int l = depth(node.leftNode);
int r = depth(node.RightNode);
if (l > r) return l + 1;
else return r + 1;
}
最小深度
给定一个二叉树,找出其最小深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
\
20
/
15
返回它的最大深度 2,而不是0。
注意:要注意到只有一个子节点的情况,因为最小深度是根节点到最近叶子节点的过程中节点的个数
public int mindepth(TreeNode root) {
if(root == null)
return 0;
if(root.left !=null && root.right!=null)
return Math.min(mindepth(root.left),mindepth(root.right))+1;
else if(root.left !=null)
return mindepth(root.left)+1;
else
return mindepth(root.right)+1;
}
注意:不能直接如下写,因为深度到达的节点必须是叶子节点
public int mindepth(TreeNode root) {
if(root == null)
return 0;
return Math.min(mindepth(root.left),mindepth(root.right))+1;
}
复制二叉树
public static TreeNode cloneTree(TreeNode root){
TreeNode node=null;
if(root==null) return null;
node = new TreeNode(root.data);
node.leftNode = cloneTree(root.leftNode);
node.RightNode = cloneTree(root.RightNode);
return node;
}
二叉树节点个数
public int sumNode(Node node){
if(node==null){
return 0;
}else{
int a=sumNode(node.getLeftChild());
int b=sumNode(node.getRightChild());
return 1+a+b;
}
}
二叉树叶子节点个数
int count=0;
public void getCountLeaf(TreeNode root) {
if(root == null) {
return;
}
if(root.left == null && root.right == null) {
count++;
}
getCountLeaf(root.left);
getCountLeaf(root.right);
}
二叉树中第K层节点的个数
public void leveOrder(TreeNode node,int level){
if (node == null || level < 1)return;
if ( level == 1){
System.out.println(node.data);
return;
}
leveOrder(node.leftNode,level - 1);
leveOrder(node.RightNode,level - 1);
}
销毁二叉树
BiTree DestroyBiTree(BiTree T) {
if (T != null) {
if (T.lchild != null) {
T.lchild = DestroyBiTree(T.lchild);
}
if (T.rchild != null) {
T.rchild = DestroyBiTree(T.rchild);
}
T = null;
}
return T;
}
反转二叉树或二叉树的镜像
public void Mirror(TreeNode root) {
if(root == null) {
return;
}
if((root.leftNode == null) && (root.RightNode == null)) {
return;
}
TreeNode temp = root.leftNode;
root.leftNode = root.RightNode;
root.RightNode = temp;
Mirror(root.leftNode);
Mirror(root.RightNode);
}
两棵二叉树是否互为镜像
- 先序遍历
- 先比较根节点,树1的左子树和树2的右子树比较,树1的右子树和树2的左子树比较
public boolean isMirror(TreeNode t1,TreeNode t2){
if(t1==null&&t2==null){
return true;
}
if(t1==null||t2==null){
return false;
}
if(t1.val != t2.val){
return false;
}
return isMirror(t1.left,t2.right)&&isMirror(t1.right,t2.left);
}
判断某个二叉树是否对称
public boolean isSymmetric(TreeNode root) {
if (root == null)
return true;
else
return isMirror(root.left, root.right);
}
public boolean isMirror(TreeNode t1,TreeNode t2){
if(t1==null&&t2==null){
return true;
}
if(t1==null||t2==null){
return false;
}
if(t1.val != t2.val){
return false;
}
return isMirror(t1.left,t2.right)&&isMirror(t1.right,t2.left);
}
二叉树中和为某一值的路径
(路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径)
class Solution {
List<List<Integer>> res=new ArrayList<>();
List<Integer> temp=new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int sum) {
findPath(root,sum);
return res;
}
public void findPath(TreeNode root,int sum){
if(root!=null){
temp.add(root.val);
if(root.left==null&&root.right==null&&(sum-root.val==0)){
res.add(new ArrayList(temp));
}
findPath(root.left,sum-root.val);
findPath(root.right,sum-root.val);
temp.remove(temp.size()-1);
}
}
}
二叉搜索树的第k个节点
TreeNode KthNode(TreeNode pRoot, int k)
{
if (k <= 0) {
return null;
}
ArrayList<TreeNode> resultLists = new ArrayList<>();
inOrder(pRoot, resultLists, k);
if (k > resultLists.size()) {
return null;
}
return resultLists.get(k - 1);
}
public void inOrder(TreeNode root, ArrayList<TreeNode> resultLists, int k) {
if (resultLists.size() >= k) {
return;
}
if (root != null) {
inOrder(root.left, resultLists, k);
resultLists.add(root);
inOrder(root.right, resultLists, k);
}
}
判断两个二叉树是否相等
public boolean isSameTree(TreeNode tree1,TreeNode tree2){
if (tree1==null&&tree2==null){
return true;
}
else if (tree1==null||tree2==null){
return false;
}
if(tree1!=null&&tree2!=null){
if(tree1.val!=tree2.val){
return false;
}
else {
return isSameTree(tree1.left,tree2.left)&&isSameTree(tree1.right,tree2.right);
}
}
return false;
}
检查是否为二叉搜索树
public boolean checkBST(TreeNode root) {
return check(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean check(TreeNode root, long min, long max) {
if (root == null) return true;
if (root.val <= min || root.val >= max) return false;
return check(root.left, min, root.val)
&& check(root.right, root.val, max);
}
Attention:
注意参数min,max不可用Integer.MIN_VALUE,Integer.MAX_VALUE,因为节点的val是int类型,所以会存在样例通不过 if (root.val <= min || root.val >= max) return false; 的情况
寻找下一个节点
请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。
给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。
保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。
import java.util.*;
public class Successor {
public int findSucc(TreeNode root, int p) {
boolean isFound = false;
Stack<TreeNode> stack = new Stack<>();
TreeNode curNode = root;
while(curNode != null || !stack.isEmpty()){
while(curNode != null){
stack.add(curNode);
curNode = curNode.left;
}
if(!stack.isEmpty()){
TreeNode q = stack.pop();
if(isFound)
return q.val;
else if(q.val == p)
isFound = true;
curNode = q.right;
}
}
return -1;
}
}
判断完全二叉树
public boolean checking(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
boolean leaf = false;
TreeNode left;
TreeNode right;
queue.add(root);
while (!queue.isEmpty()) {
root = queue.poll();
left = root.left;
right = root.right;
if ((leaf&&(left!=null||right!=null)) || (left==null&&right!=null)) {
return false;
}
if (left != null) {
queue.offer(root.left);
}
if (right != null) {
queue.offer(root.right);
}else {
leaf = true;
}
}
return true;
}
参考链接
二叉树基本操作及面试题(你想要的都有)
一篇文章搞定面试中的二叉树题目(java实现)