二叉树:树的每个节点最多只能有两个子节点。
树的效率:查找节点的时间取决于这个节点所在的层数,每一层最多有2n-1个节点,总共N层共有2n-1个节点,那么时间复杂度为O(logN),底数为2。
二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
遍历:
- 前序是根节点-左子树-右子树
- 中序是左子树-根节点-右子树
- 后序是左子树-右子树-根节点
二叉树的前、中、后序遍历
前序遍历
递归
public void preorderBT(BinaryTree root) {
//结束条件
if (root == null)
return;
//递归主体
System.out.print(root.val + " ");
preorderBT(root.left);
preorderBT(root.right);
}
非递归
/**
* 前序遍历非递归方式实现
* 非递归实现思路:二叉树遍历的递归实现很简单,也很容易理解,在进行非递归实现时,需要用到栈这种数据结构(为什么是栈,不是别的数据结构)。
* 因为递归实现的过程就是程序自己在处理圧栈和弹栈,改用非递归实现时,用栈模拟系统的圧栈与弹栈,就可以了。
*/
public List<Integer> preorderBT1(BinaryTree root) {
List<Integer> preorderResult = new ArrayList<>();
Stack<BinaryTree> stack = new Stack<>();
BinaryTree currentNode = root;
while (currentNode != null || !stack.isEmpty()) {
//对于前序遍历,需要一直往二叉树的左子树上走,直道左子树走完。在走左子树的过程中需要输出遇到节点的值
while (currentNode != null) {
preorderResult.add(currentNode.val);
stack.push(currentNode);
currentNode = currentNode.left;
}
//左边的节点都走完了,需要改变节点方向
if (!stack.isEmpty()) {
currentNode = stack.pop();
currentNode = currentNode.right;
}
}
return preorderResult;
}
中序遍历
递归
public void inorderBT(BinaryTree root) {
if (root == null)
return;
inorderBT(root.left);
System.out.print(root.val + " ");
inorderBT(root.right);
}
非递归
/**
* 中序遍历的非递归实现,与上述前序遍历类似,只有稍许不同,注意
*/
public List<Integer> inorderBT1(BinaryTree root) {
List<Integer> inorderResult = new ArrayList<>();
Stack<BinaryTree> stack = new Stack<>();
BinaryTree currentNode = root;
while (currentNode != null || !stack.isEmpty()) {
//一直向左,但是先不打印经历的节点的值
while (currentNode != null) {
stack.push(currentNode);
currentNode = currentNode.left;
}
//到达最左边,打印并改变方向
if (!stack.isEmpty()) {
currentNode = stack.pop();
inorderResult.add(currentNode.val);
currentNode = currentNode.right;
}
}
return inorderResult;
}
后序遍历
递归
public void postorderBT(BinaryTree root) {
if (root == null)
return;
postorderBT(root.left);
postorderBT(root.right);
System.out.print(root.val+" ");
}
非递归
/**
* 后序遍历的非递归实现
* 技巧:妙用前序遍历的非递归可以实现后序遍历的非递归实现,这里需要注意几点改变:后序时,先遍历右,再遍历左,最后将得到的结果反向就好了
*/
public List<Integer> postorderBT1(BinaryTree root) {
List<Integer> postorderResult = new ArrayList<>();
Stack<BinaryTree> stack = new Stack<>();
BinaryTree currentNode = root;
while (currentNode != null || !stack.isEmpty()) {
while (currentNode != null) {
postorderResult.add(currentNode.val);
stack.push(currentNode);
currentNode = currentNode.right;
}
if (!stack.isEmpty()) {
currentNode = stack.pop();
currentNode = currentNode.left;
}
}
Collections.reverse(postorderResult);
return postorderResult;
}
二叉树的最大深度
public int maxDepth(TreeNode root) {
return root==null? 0 : Math.max(maxDepth(root.left), maxDepth(root.right))+1;
}
平衡二叉树
思路:递归
private boolean result = true;
public boolean isBalanced(TreeNode root) {
maxDepth(root);
return result;
}
public int maxDepth(TreeNode root) {
if (root == null)
return 0;
int l = maxDepth(root.left);
int r = maxDepth(root.right);
//左右子数最大深度差值大于1
if (Math.abs(l - r) > 1)
//不是平衡二叉树
result = false;
return 1 + Math.max(l, r);
}
对称二叉树
思路:递归
public boolean isSymmetric(TreeNode root) {
return isMirror(root, root);
}
public boolean isMirror(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) {
return true;
}
if (t1 == null || t2 == null) {
return false;
}
return (t1.val == t2.val)
&& isMirror(t1.right, t2.left)
&& isMirror(t1.left, t2.right);
}
翻转二叉树
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode right = invertTree(root.right);
TreeNode left = invertTree(root.left);
root.left = right;
root.right = left;
return root;
}