参考Java实现二叉树算法
自己重写了部分代码,便于巩固和复习,其中最后几个题目没有测试,后两个题目没有实现,有点难度,以后有机会再去探索。
package com.xpn.tree;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import javax.naming.LinkLoopException;
import javax.swing.RootPaneContainer;
/**
* http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目
* http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树
*
* TODO: 一定要能熟练地写出所有问题的递归和非递归做法!
*
* 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代)
* 2. 求二叉树的深度: getDepthRec(递归),getDepth
* 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec
* (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2)
* 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法!)
* 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL
* 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel
* 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf
* 8. 判断两棵二叉树是否相同的树:isSameRec, isSame
* 9. 判断二叉树是不是平衡二叉树:isAVLRec
* 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):mirrorRec, mirrorCopyRec
* 10.1 判断两个树是否互相镜像:isMirrorRec
* 11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2
* 12. 求二叉树中节点的最大距离:getMaxDistanceRec
* 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec
* 14.判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec
*
*/
public class Main {
/**
* @param args
*
1
/ \
2 3
/ \ \
4 5 6
*/
private static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
TreeNode r1 = new TreeNode(1);
TreeNode r2 = new TreeNode(2);
TreeNode r3 = new TreeNode(3);
TreeNode r4 = new TreeNode(4);
TreeNode r5 = new TreeNode(5);
TreeNode r6 = new TreeNode(6);
r1.left = r2;
r1.right = r3;
r2.left = r4;
r2.right = r5;
r3.right = r6;
System.out.println(getNodeNumLeaf(r1));
}
//1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代)
private static int getNodeNumRec(TreeNode root){
if(root==null)
return 0;
return getNodeNumRec(root.left)+getNodeNumRec(root.right)+1;
}
private static int getNodeNum(TreeNode root){
if(root==null)
return 0;
Stack<TreeNode> stacks=new Stack<TreeNode>();
stacks.push(root);
int len=0;
while(!stacks.empty()){//层次遍历
TreeNode cur=stacks.pop();
len++;
if(cur.left!=null){
stacks.push(cur.left);
}
if(cur.right!=null){
stacks.push(cur.right);
}
}
return len;
}
//2. 求二叉树的深度: getDepthRec(递归),getDepth
private static int getDepthRec(TreeNode root){
if(root==null){
return 0;
}
return getDepthRec(root.left)>getDepthRec(root.right)
?getDepthRec(root.left)+1:getDepthRec(root.right)+1;
}
private static int getDepth(TreeNode root){
if(root==null){
return 0;
}
int depth=0;
int curNodes=1;//当前层的节点数
int nextNodes=0;//下一层的节点数
LinkedList<TreeNode> queue=new LinkedList<TreeNode>() ;
queue.add(root);
while(!queue.isEmpty()){
curNodes--;
TreeNode cur=queue.remove();
if(cur.left!=null){
nextNodes++;
queue.add(cur.left);
}
if(cur.right!=null){
queue.add(cur.right);
nextNodes++;
}
if(curNodes==0){//当前层遍历完毕
depth++;
curNodes=nextNodes;
nextNodes=0;
}
}
return depth;
}
//3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec
//* (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2)
private static void preorderTraversalRec(TreeNode root){
if(root==null)
return;
System.out.print(root.val+" ");
if(root.left!=null){
preorderTraversalRec(root.left);
}
if(root.right!=null){
preorderTraversalRec(root.right);
}
}
private static void preorderTraversal(TreeNode root){
if(root==null)
return;
Stack<TreeNode> stacks=new Stack<TreeNode>();
stacks.push(root);
while(!stacks.empty()){
TreeNode cur=stacks.pop();
System.out.print(cur.val + " ");
if(cur.right!=null){
stacks.push(cur.right);
}
if(cur.left!=null){
stacks.push(cur.left);
}
}
}
private static void inorderTraversalRec(TreeNode root){
if(root==null)
return;
inorderTraversalRec(root.left);
System.out.print(root.val+" ");
inorderTraversalRec(root.right);
}
private static void inorderTraversal(TreeNode root){
if(root==null)
return;
Stack<TreeNode> stacks=new Stack<TreeNode>();
TreeNode cur=root;
while(true){
while(cur!=null){
stacks.push(cur);
cur=cur.left;
}//查找最左边的
if(stacks.empty()){
break;
}
cur=stacks.pop();
System.out.print(cur.val+" ");
cur=cur.right;
}
}
private static void postorderTraversalRec(TreeNode root){
if(root==null){
return;
}
postorderTraversalRec(root.left);
postorderTraversalRec(root.right);
System.out.print(root.val+" ");
}
private static void postorderTraversal(TreeNode root){
if(root==null){
return;
}
//两个stack进行维护
Stack<TreeNode> stacks=new Stack<TreeNode>();
Stack<TreeNode> result=new Stack<TreeNode>();//存放结果的栈
stacks.push(root);
TreeNode cur=null;
while(!stacks.empty()){
cur=stacks.pop();
result.push(cur);
if(cur.left!=null){
stacks.push(cur.left);
}
if(cur.right!=null){
stacks.push(cur.right);
}
}
while(!result.empty()){
System.out.print(result.pop().val+" ");
}
}
//4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法!)
private static void levelTraversal(TreeNode root){
if(root==null)
return;
LinkedList<TreeNode> queue=new LinkedList<TreeNode>();
queue.add(root);
TreeNode cur=null;//队列实现层次遍历
while(!queue.isEmpty()){
cur=queue.pop();
System.out.print(cur.val+" ");
if(cur.left!=null){
queue.add(cur.left);
}
if(cur.right!=null){
queue.add(cur.right);
}
}
}
//比较难,使用列表嵌套列表,将每一层的元素作为一个列表进行存储
private static void levelTraversalRec(TreeNode root){
if(root==null)
return;
List<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
dfs(root, 0, res);
System.out.println(res);
}
private static void dfs(TreeNode root,int level,List<ArrayList<Integer>> res){
if(root==null)
return;
if(level>=res.size()){//添加新的层
res.add(new ArrayList<Integer>());
}
res.get(level).add(root.val);
dfs(root.left, level+1, res);
dfs(root.right, level+1, res);
}
//5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL
private static void convertBST2DLLRec(TreeNode root) {
if(root==null)
return;
root=convertBST2DLLsubRec(root);
while(root.left!=null){
root=root.left;
}
}
private static TreeNode convertBST2DLLsubRec(TreeNode root) {
if(root==null||root.left==null&&root.right==null)
return root;
TreeNode tmp=null;
if(root.left!=null){
tmp=convertBST2DLLsubRec(root.left);//处理左子节点
while(tmp.right!=null){//找最右节点
tmp=tmp.right;
}
tmp.right=root;
root.left=tmp;
}
if(root.right!=null){
tmp=convertBST2DLLsubRec(root.right);//处理右子节点
while(tmp.left!=null){//找最左节点
tmp=tmp.left;
}
tmp.left=root;
root.right=tmp;
}
return root;
}
//中序遍历进行修改
private static TreeNode convertBST2DLL(TreeNode root) {
TreeNode head=null;
TreeNode cur=root;
Stack<TreeNode> stacks=new Stack<TreeNode>();
TreeNode old = null; // 指向前一个处理的节点
while(true){
while(cur!=null){
stacks.push(cur);
cur=cur.left;
}
if(stacks.empty()){
break;
}
// 因为此时已经没有左孩子了,所以输出栈顶元素
cur=stacks.pop();
if(old!=null)
old.right=cur;
if(head == null){ // /第一个节点为双向链表头节点
head = cur;
}
old=cur;
cur=cur.right;
}
return head;
}
//6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel
private static int getNodeNumKthLevelRec(TreeNode root,int k) {
if(root==null||k<=0)
return 0;
if(k==1)
return 1;
return getNodeNumKthLevelRec(root.left, k-1)+getNodeNumKthLevelRec(root.right, k-1);
}
//队列 层次遍历
private static int getNodeNumKthLevel(TreeNode root,int k) {
if(root==null||k<=0)
return 0;
if(k==1)
return 1;
int curNodes=1;
int nextNodes=0;
TreeNode cur=root;
LinkedList<TreeNode> queue=new LinkedList<TreeNode>();
queue.push(cur);
int i=1;
while (!queue.isEmpty()&& i<k) {
cur=queue.remove();
curNodes--;
if(cur.left!=null){
queue.add(cur.left);
nextNodes++;
}
if(cur.right!=null){
queue.add(cur.right);
nextNodes++;
}
if(curNodes==0){
curNodes=nextNodes;
nextNodes=0;
i++;
}
}
return curNodes;
}
//7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf
private static int getNodeNumLeafRec(TreeNode root){
if(root==null){
return 0;
}
if(root.left==null&&root.right==null)
return 1;
return getNodeNumLeafRec(root.left)+getNodeNumLeafRec(root.right);
}
private static int getNodeNumLeaf(TreeNode root){
if(root==null){
return 0;
}
int counts=0;
Stack<TreeNode> stacks=new Stack<TreeNode>();
stacks.push(root);
TreeNode cur=null;
while(!stacks.empty()){
cur=stacks.pop();
if(cur.right!=null){
stacks.push(cur.right);
}
if(cur.left!=null){
stacks.push(cur.left);
}
if(cur.left==null&&cur.right==null){
counts++;
}
}
return counts;
}
//8. 判断两棵二叉树是否相同的树:isSameRec, isSame
private static boolean isSameRec(TreeNode t1,TreeNode t2){
if(t1==null&&t2==null)
return true;
if(t1==null||t2==null)
return false;
if(t1.val==t2.val)
return true;
return isSameRec(t1.left, t2.left)&&isSameRec(t1.right, t2.right);
}
private static boolean isSame(TreeNode t1,TreeNode t2){
if(t1==null&&t2==null)
return true;
if(t1==null||t2==null)
return false;
Stack<TreeNode> s1=new Stack<TreeNode>();
Stack<TreeNode> s2=new Stack<TreeNode>();
s1.push(t1);
s2.push(t2);
TreeNode cur1=null;
TreeNode cur2=null;
while(!s1.empty()&&!s2.empty()){
cur1=s1.pop();
cur2=s2.pop();
if(cur1.left!=null)
s1.push(cur1.left);
if(cur1.right!=null)
s1.push(cur1.right);
if(cur2.left!=null)
s2.push(cur2.left);
if(cur2.right!=null)
s2.push(cur2.left);
if(cur1.val!=cur2.val)
return false;
}
if(!s1.empty()||!s2.empty())
return false;
return true;
}
//9. 判断二叉树是不是平衡二叉树:isAVLRec
private static boolean isAVLRec(TreeNode root){
if(root==null)
return true;
if(Math.abs(getDepth(root.left)-getDepth(root.right))>1)
return false;
return isAVLRec(root.left)&&isAVLRec(root.right);
}
//10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):mirrorRec, mirrorCopyRec
// 10.1 判断两个树是否互相镜像:isMirrorRec
private static TreeNode mirrorRec(TreeNode root){
if(root==null)
return null;
TreeNode tmp=mirrorRec(root.left);
root.left=mirrorRec(root.right);
root.right=tmp;
return root;
}
//11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2
private static TreeNode getLastCommonParentRec(TreeNode root,TreeNode t1,TreeNode t2){
if(findNodeRec(root.left,t1)){//t1在左子树
if(findNodeRec(root.right, t2))//t2在右子树
return root;
else {
return getLastCommonParentRec(root.left, t1, t2);
}
}else {
if(findNodeRec(root.left, t2))//t2在左子树
{
return root;
}else {
return getLastCommonParentRec(root.right, t1, t2);
}
}
}
// 帮助方法,递归判断一个点是否在树里
private static boolean findNodeRec(TreeNode root, TreeNode node) {
if(root==null||node==null)
return false;
if(root==node){
return true;
}
boolean isfound=findNodeRec(root.left, node);
if(!isfound)
isfound=findNodeRec(root.right, node);
return isfound;
}
}