如何构建一棵二叉树
我们输入一个字符串,构成二叉树的形式,然后进行前中后,层序,深度遍历;
输入:"[1,2,3,4,5,6,7,8]"
使用链表来存放当前节点的左右孩子,链表可以当作一个双端队列来使用,队头拿出当前节点并删除,队尾插入当前节点的左右孩子。
使用一个变量index来控制分割字符串后形成数组元素的个数,当index=数组.length()的时候,退出循环,已经到达数组中的最后一个数字处了。
package Tree;
import java.util.LinkedList;
import java.util.Queue;
public class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode(int x){
val=x;
}
@Override
public String toString() {
return "["+val+"]";
}
public static TreeNode stringToTreeNode(String input) {
// 处理"[","]"
input = input.trim();
input = input.substring(1, input.length() - 1);
if (input.length() == 0) {
return null;
}
// 分割字符串,获取根结点
String[] parts = input.split(",");
String item = parts[0];
TreeNode root = new TreeNode(Integer.parseInt(item));
// 将根结点加入到双链表中
Queue<TreeNode> nodeQueue = new LinkedList<>();
nodeQueue.add(root);
int index = 1;
// 遍历双链表
while (!nodeQueue.isEmpty()) {
// 获取双链表的头结点作为当前结点
TreeNode node = nodeQueue.remove();
// 判断是否还有结点可以构建左子
if (index == parts.length) {
break;
}
// 构建当前结点的左子
item = parts[index++];
item = item.trim();
// 判断左子是否为空
if (!item.equals("null")) {
int leftNumber = Integer.parseInt(item);
node.left = new TreeNode(leftNumber);
// 将左子加到双链表中
nodeQueue.add(node.left);
}
// 判断是否还有结点可以构建右子
if (index == parts.length) {
break;
}
// 构建当前结点的右子
item = parts[index++];
item = item.trim();
// 判断右子是否为空
if (!item.equals("null")) {
int rightNumber = Integer.valueOf(item);
node.right = new TreeNode(rightNumber);
nodeQueue.add(node.right);
}
}
return root;
}
}
二叉树的前序遍历
二叉树前序遍历的递归过程:根左右
public static void preOrder(TreeNode root){
if(root==null){
return;
}
System.out.println(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
非递归版本:
根据画图打印的结果为:1,2,4,8,5,3,6,7
Java代码递归和非递归:
package Tree;
import java.util.Stack;
public class PreOrder {
//前序遍历 非递归写法
//非递归写法,先把二叉树的右子树节点放入栈中,然后压入左节点,
public static void preOrder2(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> stack=new Stack<>();
stack.push(root);
while(!stack.empty()){
TreeNode q=stack.pop();
System.out.println(q.val+" ");
//先把右节点压入栈中
if(q.right!=null){
stack.push(q.right);
}
//再压入左节点
if(q.left!=null){
stack.push(q.left);
}
}
}
}
二叉树的中序遍历
递归代码也非常简单,左根右的方式
public static void inOrderTraversal(TreeNode root){
if(root==null){
return;
}
inOrderTraversal(root.left);
System.out.println(root.val);
inOrderTraversal(root.right);
}
非递归:
非递归代码
package Tree;
import java.util.Stack;
public class InOrderTraversal {
//非递归遍历
public static void inOrderTraversal2(TreeNode root){
Stack<TreeNode> stack=new Stack<>();
while(root!=null||!stack.isEmpty()){
while(root!=null){
stack.push(root);
root=root.left;
}
if(!stack.isEmpty()){
root=stack.pop();
System.out.println(root.val);
root=root.right;
}
}
}
}
二叉树的后序遍历
递归:
public static void postOrder(TreeNode root){
if(root==null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.println(root.val);
}
非递归:使用两个栈stack1,stack2来存储,放入stack1的顺序为根左右,放入stack2的顺序为根右左,最后从栈stack2中打印出最后的结果为:左右根。
package Tree;
import java.util.Stack;
public class PostOrder {
//非递归版本
public static void postOrder2(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> s1=new Stack<>();
Stack<TreeNode> s2=new Stack<>();
s1.push(root);
while(!s1.isEmpty()){
root=s1.pop();
s2.push(root);
while(root.left!=null){
s1.push(root.left);
}
while(root.right!=null){
s1.push(root.right);
}
}
while(!s2.isEmpty()){
System.out.println(s2.pop().val+" ");
}
}
public static void postOrder3(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> s1=new Stack<>();
Stack<TreeNode> s2=new Stack<>();
}
}
二叉树的层序遍历(BFS)
递归:
public static void levelOrder2(TreeNode root){
int depth=GetHeight(root);
for(int level=0;level<depth;level++){
printLevel(root,level);
}
}
public static void printLevel(TreeNode root,int level){
if(root==null){
return;
}
if(level==0) {
System.out.println(root.val);
}else {
printLevel(root.left, level - 1);
printLevel(root.right, level - 1);
}
}
public static int GetHeight(TreeNode root){
if(root==null){
return 0;
}
int leftHigh=GetHeight(root.left);
int rightHigh=GetHeight(root.right);
return Math.max(leftHigh,rightHigh)+1;
}
非递归:
package Tree;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LevelOrder {
public static void levelOrder(TreeNode root){
if(root==null){
return;
}
//链表,在这里我们可以把它看成是一个队列
LinkedList<TreeNode> list=new LinkedList<>();
list.add(root);//把元素添加到队尾
while(!list.isEmpty()){
//移除队头元素
TreeNode node=list.poll();
System.out.println(node.val);
if(node.left!=null){
list.add(node.left);
}
if(node.right!=null){
list.add(node.right);
}
}
}
把二叉树层序遍历结果存储到list中
//如果想把遍历的结果放到list中存储
public static List<List<Integer>> levelOrder3(TreeNode root){
if(root==null){
return null;
}
List<List<Integer>> list=new ArrayList<>();
bfs(root,0,list);
return list;
}
public static void bfs(TreeNode root,int level,List<List<Integer>> list){
if(root==null){
return;
}
if(level>list.size()){
List<Integer> subList=new ArrayList<>();
subList.add(root.val);
list.add(subList);
}else{
list.get(level).add(root.val);
}
bfs(root.left,level+1,list);
bfs(root.right,level+1,list);
}
}
二叉树的深度遍历(DFS)
递归:深度遍历和前序遍历遍历的结果是一样的。
//递归版本
public static void dfs2(TreeNode root){
if(root==null){
return;
}
System.out.println(root.val);
dfs2(root.left);
dfs2(root.right);
}
}
非递归:也和前序遍历代码是一样的,同一种方式遍历的不同叫法。
package Tree;
import java.util.Stack;
public class DFS {
public static void dfs(TreeNode root){
Stack<TreeNode> stack=new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node=stack.pop();
System.out.println(node.val);
if(node.right!=null){
stack.push(node.right);
}
if(node.left!=null){
stack.push(node.left);
}
}
}
测试代码
package Tree;
import static Tree.TreeNode.stringToTreeNode;
public class TestDemo {
public static void main(String[] args) {
String input="[1,2,4,5,3,6]";
TreeNode root = stringToTreeNode(input);
//PreOrder.preOrder(root);
//InOrderTraversal.inOrderTraversal(root);
//PostOrder.postOrder(root);
// LevelOrder.levelOrder(root);
DFS.dfs2(root);
}
}