二叉树的各种操作(递归和非递归遍历,树深度,结点个数等等)(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);
}
}
运行效果如下图:
相关文章推荐
- java语言实现的二叉树的各种操作(包括递归与非递归遍历二叉树,求二叉树的高度,节点总数,叶子节点等)
- 二叉树的基本操作(创建、递归和非递归遍历、求深度、求叶子数)
- 二叉树的相关操作:创建、查找、求高度和深度、各种遍历(前、中、后、层序)等等
- 二叉树实现(包括遍历等各种操作,递归与非递归)
- 二叉树先序后序递归建立,前中后序层次非递归遍历,以及统计叶子结点个数以及树的深度
- 八.二叉树各种操作的C语言实现 二叉树中各种遍历的非递归和递归算法的实现
- 二叉树操作(插入、删除、遍历(递归与非递归))
- Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】
- java实现二叉树的前中后遍历(递归和非递归)
- 二叉树的建树、遍历(先序、中序、后序、层次)(递归和非递归)--Java实现
- 八.二叉树各种操作的C语言实现 深度遍历求深度,广度遍历求深度,交换左右子树,求叶子节点数
- 华南理工数据结构大作业第二题 二叉树各种操作深度结点个数后序前序中序层次求祖先
- 二叉树的遍历,递归和非递归,求深度
- 用非递归实现二叉树的前序、中序、后序、层次遍历,用递归实现查找、统计个数、比较、求深度
- 用java实现二叉树相关操作(前序建树,前中后递归非递归遍历,层序遍历)
- 【leetcode Java】二叉树的递归遍历以及最大深度的求解(Java)
- Java实现二叉树的遍历(递归和非递归)
- 二叉树的建立(非递归建立与定义建立)与基本操作(广度和深度遍历,求叶子树高)实现
- 二叉树的几种遍历递归与非递归java实现
- 二叉树的前、中、后序遍历(递归和非递归)、层序遍历、深度、叶子节点个数