您的位置:首页 > 编程语言 > Java开发

二叉树的各种操作(递归和非递归遍历,树深度,结点个数等等)(Java)

2018-04-03 19:39 851 查看

目录

建立二叉树

递归前序和非递归前序

递归中序和非递归中序

递归后续和非递归后续(包括双栈法和设置pre结点)

层次遍历

寻找树中有没有值为x的结点

统计树中结点的个数

计算树的高度

判断两颗树是不是相等

二叉树建立

可以根据二叉树根节点和左右子结点的下标关系递归建立二叉树,层次输入二叉树结点,递归建立,代码如下:

public static TreeNode CreateTree(int val[],int i) {
if(i >= val.length || val[i] == -1)return null;
TreeNode T = new TreeNode(val[i]);
T.left = CreateTree(val,2*i + 1);
T.right = CreateTree(val,2*i + 2);
return T;
}


前序遍历

递归前序:

public static void PreOrder(TreeNode T) {
if(null != T) {
System.out.print(T.val + " ");
PreOrder(T.left);
PreOrder(T.right);
}
}


非递归前序遍历:

前序遍历可以归纳为: 根结点->左子树->右子树,所以对于正在访问的根结点,可以直接访问,访问完之后,按照相同的方式访问左子树,再访问右子树,过程如下 :

访问结点p,并将结点p入栈。

判断结点p的左孩子是否为空,若不为空,则继续访问左孩子,否则将栈顶元素出栈,并访问栈顶的元素的有孩子。

直到栈为空且p为空,循环结束。

//非递归的前序遍历
public static void Nonrecursive_PreOrder(TreeNode T) {
Stack<TreeNode>s = new Stack<TreeNode>();
TreeNode p = T;
while(!(s.empty()) || p != null) {
if(p != null) {
s.push(p);
System.out.print(p.val + " ");
p = p.left;
}
else {
p = s.pop();
p = p.right;
}
}
}


中序遍历

递归中序:

public static void InOrder(TreeNode T) {
if(null != T) {
InOrder(T.left);
System.out.print(T.val + " ");
InOrder(T.right);
}
}


非递归中序:

中序遍历 : 左子树->根->右子树,过程如下:

对于任意结点p,若其左孩子不为空,则将p入栈,并将p的左孩子置为当前的p。然后对当前结点p再进行相同的处理。

若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将栈顶结点的右孩子置为当前的p结点。

直到栈为空且p为空,循环结束。

//非递归中序
public static void Nonrecursive_Inorder(TreeNode T) {
Stack<TreeNode>s = new Stack<TreeNode>();
TreeNode p = T;
while(!(s.empty()) || p != null) {
if(p != null) {
s.push(p);
p = p.left;
}else {
p = s.pop();
System.out.print(p.val + " ");
p = p.right;
}
}
}


后序遍历

递归后序:

public static void PostOrder(TreeNode T) {
if(null != T) {
PostOrder(T.left);
PostOrder(T.right);
System.out.print(T.val + " ");
}
}


非递归后序:

>

双栈法 : 对于当前结点p,将其pop出来并push到s2栈,然后如果按照左->右的顺序到s,然后每个都右pop出来,push到s2,所以等下输出s2的时候顺序还是左子树->右子树->根

设置pre结点 : 对于任一结点p,先将其入栈。若p不存在左孩子和右孩子,则可以直接访问它。或者p存在左孩子或者右孩子,但是左孩子和右孩子都已经被访问过了,则可以直接访问该结点。

若非上述两种情况,则将右孩子和左孩子依次入栈。这样可以保证每次取栈顶元素时,左孩子在右孩子前面被访问,根结点在左孩子和右孩子访问之后被访问。

//非递归后续1(双栈法解决非递归后续)
public static void Nonrecursive_PostOrder_1(TreeNode T){
Stack<TreeNode>s = new Stack<TreeNode>(),s2 = new Stack<TreeNode>();
TreeNode p = T;
s.push(T);
while(!s.empty()) {
p = s.pop();
s2.push(p);
if(p.left != null)s.push(p.left);
if(p.right != null)s.push(p.right);
}
while(!s2.empty()
4000
)System.out.print(s2.pop().val + " ");
}

//非递归后续2(设置pre结点)
public static void Nonrecursive_PostOrder_2(TreeNode T){
TreeNode cur,pre = null;
Stack<TreeNode>s = new Stack<TreeNode>();
s.push(T);
while(!s.empty()) {
cur = s.peek();
if((cur.left == null && cur.right == null) || ((pre != null) && (pre == cur.left || pre == cur.right))) {
System.out.print(cur.val + " ");
s.pop();
pre = cur;
}else {
if(cur.right != null)s.push(cur.right);
if(cur.left != null)s.push(cur.left);
}
}
}


层次遍历

利用队列BFS即可,每次访问完p,若左右孩子存在,则入队,直至队空

public static void LevelOrder(TreeNode T) {
Queue<TreeNode>q = new LinkedList<TreeNode>();
if(T != null) {
q.add(T);
while(!q.isEmpty()) {
TreeNode now = q.poll();
System.out.print(now.val + " ");
if(now.left != null)q.add(now.left);
if(now.right != null)q.add(now.right);
}
}
}


寻找树中有没有值为x的结点

递归条件有两个,一个是为空代表没找到,找到了的话直接返回,否则递归查找左右子树。

//查找某个结点的值为x
public static TreeNode Search_Tree(TreeNode T,int x) {
if(T == null) return null;
if(T.val == x) return T;
else {
if(Search_Tree(T.left,x) == null)  return Search_Tree(T.right,x);
else return Search_Tree(T.left,x);
}
}


统计树中结点的个数

树中结点的个数等于根节点(1) + 左子树结点个数 + 右子树的个数,递归求解即可。

//统计结点个数
public static int CountNode(TreeNode T) {
if(T != null) {
return CountNode(T.left) + CountNode(T.right) + 1;
}else return 0;
}


计算树的高度

也是递归求解,左右子树的高度中的比较高的加上根节点就是树的高度

//计算二叉树的深度
public static int TreeDepth(TreeNode T) {
if(T == null)return 0;
int l = TreeDepth(T.left);
int r = TreeDepth(T.right);
return l > r ? l + 1 : r + 1;
}


判断两棵树是不是相等

也是递归求解,两棵树相等,既要根节点的值相等,而且左右子树也要相等。

public static boolean is_SameTree(TreeNode T1,TreeNode T2) {
if(T1 == null && T2 == null)return true;
else return T1 != null && T2 != null && T1.val == T2.val && is_SameTree(T1.left,T2.left) && is_SameTree(T1.right,T2.right);
}


完整的测试代码如下 :

1
/       \
2         3
/   \      /  \
4     5    6    7
/ \   / \  / \  / \
8     9    10   11


import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class TreeNode {

private TreeNode left,right;
private int val;

public TreeNode () {this.val = 0;}

public TreeNode(int val) {
this.val = val;
}

//建立二叉树
public static TreeNode CreateTree(int val[],int i) {
if(i >= val.length || val[i] == -1)return null;
TreeNode T = new TreeNode(val[i]);
T.left = CreateTree(val,2*i + 1);
T.right = CreateTree(val,2*i + 2);
return T;
}

//递归前序
public static void PreOrder(TreeNode T) {
if(null != T) {
System.out.print(T.val + " ");
PreOrder(T.left);
PreOrder(T.right);
}
}
//非递归的前序遍历 public static void Nonrecursive_PreOrder(TreeNode T) { Stack<TreeNode>s = new Stack<TreeNode>(); TreeNode p = T; while(!(s.empty()) || p != null) { if(p != null) { s.push(p); System.out.print(p.val + " "); p = p.left; } else { p = s.pop(); p = p.right; } } }

//递归中序
public static void InOrder(TreeNode T) { if(null != T) { InOrder(T.left); System.out.print(T.val + " "); InOrder(T.right); } }
//非递归中序 public static void Nonrecursive_Inorder(TreeNode T) { Stack<TreeNode>s = new Stack<TreeNode>(); TreeNode p = T; while(!(s.empty()) || p != null) { if(p != null) { s.push(p); p = p.left; }else { p = s.pop(); System.out.print(p.val + " "); p = p.right; } } }

//递归后续
public static void PostOrder(TreeNode T) { if(null != T) { PostOrder(T.left); PostOrder(T.right); System.out.print(T.val + " "); } }

//非递归后续1(双栈法解决非递归后续)
public static void Nonrecursive_PostOrder_1(TreeNode T){
Stack<TreeNode>s = new Stack<TreeNode>(),s2 = new Stack<TreeNode>();
TreeNode p = T;
s.push(T);
while(!s.empty()) {
p = s.pop();
s2.push(p);
if(p.left != null)s.push(p.left);
if(p.right != null)s.push(p.right);
}
while(!s2.empty())System.out.print(s2.pop().val + " ");
}

//非递归后续2(设置pre结点)
public static void Nonrecursive_PostOrder_2(TreeNode T){
TreeNode cur,pre = null;
Stack<TreeNode>s = new Stack<TreeNode>();
s.push(T);
while(!s.empty()) {
cur = s.peek();
if((cur.left == null && cur.right == null) || ((pre != null) && (pre == cur.left || pre == cur.right))) {
System.out.print(cur.val + " ");
s.pop();
pre = cur;
}else {
if(cur.right != null)s.push(cur.right);
if(cur.left != null)s.push(cur.left);
}
}
}

//层次遍历
public static void LevelOrder(TreeNode T) {
Queue<TreeNode>q = new LinkedList<TreeNode>();
if(T != null) {
q.add(T);
while(!q.isEmpty()) {
TreeNode now = q.poll();
System.out.print(now.val + " ");
if(now.left != null)q.add(now.left);
if(now.right != null)q.add(now.right);
}
}
}

//查找某个结点的值为x
public static TreeNode Search_Tree(TreeNode T,int x) {
if(T == null) return null;
if(T.val == x) return T;
else {
if(Search_Tree(T.left,x) == null) return Search_Tree(T.right,x);
else return Search_Tree(T.left,x);
}
}

//统计结点个数
public static int CountNode(TreeNode T) {
if(T != null) {
return CountNode(T.left) + CountNode(T.right) + 1;
}else return 0;
}

//计算二叉树的深度
public static int TreeDepth(TreeNode T) {
if(T == null)return 0;
int l = TreeDepth(T.left);
int r = TreeDepth(T.right);
return l > r ? l + 1 : r + 1;
}

//判断两棵树是不是相等
public static boolean is_SameTree(TreeNode T1,TreeNode T2) { if(T1 == null && T2 == null)return true; else return T1 != null && T2 != null && T1.val == T2.val && is_SameTree(T1.left,T2.left) && is_SameTree(T1.right,T2.right); }

public static void main(String[] args) {
int[] data = {1,2,3,4,5,6,7,8,-1,9,-1,10,-1,11,-1};
int[] data2 = {1,2,3,4,5,6,7,8,-1,9,-1,10,-1,11,-1};
TreeNode root = CreateTree(data,0);
TreeNode root2 = CreateTree(data2,0);

System.out.println("-------前序遍历-------");
PreOrder(root);
System.out.println();
Nonrecursive_PreOrder(root);

System.out.println("\n" + "-------中序遍历-------");
InOrder(root);
System.out.println();
Nonrecursive_Inorder(root);

System.out.println("\n" + "-------后序遍历-------");
PostOrder(root);
System.out.println();
Nonrecursive_PostOrder_1(root);
System.out.println();
Nonrecursive_PostOrder_2(root);

System.out.println("\n" + "-------层次遍历-------");
LevelOrder(root);

System.out.println("\n" + "------结点个数-------");
System.out.println(CountNode(root));

System.out.println("\n" + "------二叉树深度-------");
System.out.println(TreeDepth(root));

System.out.println("\n" + "-----判断两棵树是不是相同-----");
System.out.println(is_SameTree(root,root2));

System.out.println("\n" + "-----寻找树中有没有值为3的结点-----");
TreeNode Find = Search_Tree(root,3);
if(null == Find)System.out.println("没有找到结点");
else System.out.println("这个结点的左右子结点的值是" + Find.left.val + " " + Find.right.val);
}
}


运行效果如下图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  BinaryTree TreeNode
相关文章推荐