本文主要内容:
1.用数组建树、带空结点的前序遍历
2.平衡二叉树
3.二叉树构建字符串
4.最近祖先问题
5.层序遍历
1.根据数组建树(中序、后序)
2.如何利用“前序”来构建二叉树?
方法:构建出树、返回调用者构建过程中用掉值的个数、方法需要返回两个值(定义一个类[Node root;int used])
3.输入:Scanner(java.util包下)
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext){
String line = scanner.nextLine();//读一行
String line1 = scanner.nextInt();//读字符
}
4.建树:(1)带空结点的前序遍历
(2)中序+前序、后序+中序
5.平衡二叉树:左右子树高度差不能超过1
6.二叉树构建字符串(StringBuilder)
7.最近的祖先问题
8.层序遍历(队列)
(1)把根放到队列中
(2)循环直到?队列为空
把队首结点取出
把队首结点的左右孩子放入队列(非空孩子)
9.二叉树的层序遍历(从上往下、从左到右)
队列,把根放入队列中,将队列中的第一个元素弹出,循环放入它的孩子结点(孩子结点不为空),直到队列为空。
10.满二叉树最后一行元素等于前几行元素之和+1
11.判断是否完全二叉树?
带空的层序遍历,遇到null之后是否还有not null出现,如果有:不是完全二叉树。否则:是完全二叉树
做法:层序遍历中判断遇到空后还能再次遇到元素,即不是完全二叉树
12.二叉树的非递归写法(非递归方法:栈空间更容易控制)
递归使用的栈是系统调用栈,往往空间比较小,而且一般比较固定大小的。
代码演示:
public class Node {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
public String toString(){
return value+" ";
}
}
public class Solution1 {
public static Node createTree1(){
Node a = new Node(1);
Node b = new Node(2);
Node c = new Node(3);
Node d = new Node(4);
Node e = new Node(5);
Node f = new Node(6);
a.left = b;a.right = c;
b.left = d;b.right = e;
c.left = null;c.right = null;
d.left = null;d.right = null;
e.left = null;e.right = f;
f.left = null;f.right = null;
return a;
}
//用数组建树:根据前序和中序,分别递归建立左子树和右子树,终止:数组长度为0
public static Node buildTree(int[] preOrder, int[] inOrder) {
if(preOrder.length==0){
return null;
}
int rootValue = preOrder[0];
Node root = new Node(rootValue);
int leftSize = 0;
for (int i = 0; i < inOrder.length; i++) {
if (root.value == inOrder[i]) {
leftSize = i;
}
}
int[] leftPreOrder = Arrays.copyOfRange(preOrder, 1, leftSize + 1);
int[] leftInOrder = Arrays.copyOfRange(inOrder,0,leftSize);
Node left = buildTree(leftPreOrder,leftInOrder);
root.left = left;
int[] rightPreOrder = Arrays.copyOfRange(preOrder,leftSize+1,preOrder.length);
int[] rightInOrder = Arrays.copyOfRange(inOrder,leftSize+1,inOrder.length);
Node right = buildTree(rightPreOrder,rightInOrder);
root.right = right;
return root;
}
public static Node buildTree1(int[] inOrder,int[] postOrder){
if(inOrder.length==0){
return null;
}
int rootValue = postOrder[postOrder.length-1];
Node root = new Node(rootValue);
int leftSize = 0;
for(int i = 0;i<inOrder.length;i++){
if(inOrder[i]==root.value){
leftSize = i;
}
}
int[] leftInOrder = Arrays.copyOfRange(inOrder,0,leftSize);
int[] leftPostOrder = Arrays.copyOfRange(postOrder,0,leftSize);
Node left = buildTree1(leftInOrder,leftPostOrder);
root.left = left;
int[] rightInOrder = Arrays.copyOfRange(inOrder,leftSize+1,inOrder.length);
int[] rightPostOrder = Arrays.copyOfRange(postOrder,leftSize,postOrder.length-1);
Node right = buildTree1(rightInOrder,rightPostOrder);
root.right = right;
return root;
}
static class ReturnValue{
Node root;
int used;
}
//根据一个带空树的前序遍历建树
//根+左子树+右子树,但只有一种遍历,所有需要记录左子树锁所需要的元素个数
public static ReturnValue createTreePreOrder(List<Integer> preOrder){
//首先考虑线性表为空的情况
if(preOrder.size()==0){
ReturnValue rv = new ReturnValue();
rv.root = null;
rv.used = 0;
return rv;
}
//其次考虑线性表中遇到‘#’时,用掉一个元素
int value = preOrder.get(0);
Node root = new Node(value);
if(value=='#'){
ReturnValue rv = new ReturnValue();
rv.root = null;
rv.used = 1;
return rv;
}
//将线性表分割
ReturnValue leftPreOrder = createTreePreOrder(preOrder.subList(1,preOrder.size()));
ReturnValue rightPreOrder = createTreePreOrder(preOrder.subList(1+leftPreOrder.used,preOrder.size()));
//分割树线性表的左右子树
root.left = leftPreOrder.root;
root.right = rightPreOrder.root;
//返回
ReturnValue rv = new ReturnValue();
rv.root = root;
rv.used = 1+leftPreOrder.used+rightPreOrder.used;
return rv;
}
public static void preOrderTraver(StringBuilder sb,Node root){
//首先在进行前序遍历的同时给前后以及左为空右不为空的加上括号
if(root==null){
return;
}
sb.append("(");
sb.append(root);
if(root.left==null&&root.right!=null){
sb.append("()");
}
preOrderTraver(sb,root.left);
preOrderTraver(sb,root.right);
sb.append(")");
}
//二叉树创建字符串
public static String treeStr(Node root){
if(root == null){
return "";
}
//取出字符串中[1,result.length-1)
StringBuilder sb = new StringBuilder();
preOrderTraver(sb,root);
String result = sb.toString();
return result.substring(1,result.length()-1);
}
//给定一个二叉树,找出该树两个指定节点的公共祖先
public static Boolean find(Node root,Node p){
//首先查找结点
if(root==null||p==null){
return false;
}
if(root==p){
return true;
}
if(find(root.left,p)){
return true;
}
return find(root.right,p);
}
public static Node lowerAncestor(Node root,Node p,Node q){
//判断p、q是否为root
if(root == p||root==q){
return root;
}
Boolean pLeft = find(root.left,p);
Boolean qLeft = find(root.left,q);
//判断p、q是否都在左子树上
if(pLeft&&qLeft){
return lowerAncestor(root.left,p,q);
}
//判断p、q是否都在右子树上
if(!pLeft&&!qLeft){
return lowerAncestor(root.right,p,q);
}
//p、q分别在左右子树上
return root;
}
//平衡二叉树
public static int height(Node root){
if(root == null){
return 0;
}
int leftHeight = height(root.left);
int rightHeight = height(root.right);
int max = Math.max(leftHeight,rightHeight);
return max;
}
public static boolean isBalanced(Node root){
if(root == null){
return false;
}
if(isBalanced(root.left)){
return true;
}
if(isBalanced(root.right)){
return true;
}
int leftHeight = height(root.left);
int rightHeight = height(root.right);
int diff = leftHeight-rightHeight;
// if(diff==1||diff==-1||diff==0){
// return true;
// }
if(diff>1||diff<-1){
return false;
}
return true;
}
//二叉树的层序遍历(队列)
public static void levelTraversal(Node root){
//首先判断root是否为空
if(root == null){
return;
}
Queue<Node> queue = new LinkedList<>();
//将首元素加到队列中
queue.add(root);
//若队列中还有元素就继续循环
while (!queue.isEmpty()){
//将队首元素弹出,并打印
Node front = queue.poll();
System.out.print(front.value+" ");
//将弹出元素的左右孩子结点加入到队列中去
if(front.left!=null){
queue.add(front.left);
}
if(front.right!=null){
queue.add(front.right);
}
}
}
//二叉树的层序遍历(用List)
//要将每一层的元素加到一个list中,所有要lever属性
static class Element{
Node node;
int level;
}
public static List<List<Integer>> levelTraversal1(Node root){
List<List<Integer>> list = new ArrayList<>();
//如果root为空,返回空的list
if(root == null){
return list;
}
Queue<Element> queue = new LinkedList<>();
Element element = new Element();
element.node = root;
element.level = 0;
//将root加入到对列中去
queue.add(element);
while (!queue.isEmpty()){
//将队首元素弹出并记录
Element front = queue.poll();
//线性表中每个元素又是一个线性表,当线性表的size与弹出元素的层数一致时,需要增加一个新的线性表
if(front.level==list.size()){
list.add(new ArrayList<>());
}
//如果不同,直接在线性表中加入元素
list.get(front.level).add(front.node.value);
//如果弹出元素的左右孩子都不为空,将它们加入到队列中
if(front.node.left!=null){
Element left = new Element();
left.node = front.node.left;
left.level = front.level+1;
queue.add(left);
}
if(front.node.right!=null){
Element right = new Element();
right.node = front.node.right;
right.level = front.level+1;
queue.add(right);
}
}
return list;
}
//判断是否完全二叉树
public static boolean isComplement(Node root){
Queue<Node> queue = new LinkedList<>();
queue.add(root);
while (true) {
Node front = queue.poll();
if (front == null) {
break;
}
queue.add(root.left);
queue.add(root.right);
}
while (!queue.isEmpty()){
Node node = queue.poll();
if(node!=null){
return false;
}
}
return true;
}
public static void perOrderT(Node root){
Stack<Node> stack = new Stack<>();
Node cur = root;
while(!stack.isEmpty()||cur!=null) {
while (cur != null) {
System.out.print(cur.value + " ");
stack.push(cur);
cur = cur.left;
}
Node top = stack.pop();
cur = top.right;
}
}
public static void inOrderT(Node root){
Stack<Node> stack = new Stack<>();
Node cur = root;
while(cur!=null||!stack.isEmpty()){
while (cur!=null){
stack.push(cur);
cur = cur.left;
}
Node top = stack.pop();
System.out.print(top.value+" ");
cur = top.right;
}
}
public static void postOrderT(Node root){
Stack<Node> stack = new Stack<>();
Node cur = root;
Node last = null;
while (cur!=null||!stack.isEmpty()){
while (cur!=null){
stack.push(cur);
cur = cur.left;
}
Node top = stack.peek();
if (top.right == null || top.right == last) {
stack.pop();
System.out.print(top.value+" ");
last = top;
} else {
cur = top.right;
}
}
}
public static void main(String[] args) {
int[] preOrder = {1,2,4,5,3,6};
int[] inOrder = {4,2,5,1,3,6};
int[] postOrder = {4,5,2,6,3,1};
Node n1 = buildTree(preOrder,inOrder);
System.out.println("成功");
Node n2 = buildTree1(inOrder,postOrder);
System.out.println("成功");
System.out.println("=======================");
List<Integer> list = Arrays.asList(1,2,(int)'#',(int)'#',3,(int)'#',(int)'#');
ReturnValue rv = new ReturnValue();
rv = createTreePreOrder(list);
System.out.println("成功");
System.out.println("=======================");
Node root = createTree1();
System.out.println(treeStr(root));
System.out.println("=======================");
levelTraversal(root);
System.out.println();
System.out.println("=======================");
System.out.println(isBalanced(root));
System.out.println("=======================");
List<List<Integer>> lists = levelTraversal1(root);
System.out.println(lists);
System.out.println("========================");
perOrderT(root);
System.out.println("=========================");
inOrderT(root);
System.out.println();
System.out.println("=========================");
perOrderT(root);
}
}
//运行结果:
成功
成功
=======================
成功
=======================
1 (2 (4 )(5 ()(6 )))(3 )
=======================
1 2 3 4 5 6
=======================
true
=======================
[[1], [2, 3], [4, 5], [6]]
========================
1 2 4 5 6 3
=========================
4 2 5 6 1 3
=========================
1 2 4 5 6 3