概述
package interview.src;
import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
//定义二叉树节点
class BinaryTreeNode{
int data;
BinaryTreeNode left;
BinaryTreeNode right;
public BinaryTreeNode() {
// TODO Auto-generated constructor stub
}
public BinaryTreeNode(int data) {
this.data=data;
left=null;
right=null;
}
}
public class BinaryTree_Summary {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
1
/
2 3
/
4 5 6
*/
// BinaryTreeNode r1=new BinaryTreeNode(1);
// BinaryTreeNode r2=new BinaryTreeNode(2);
// BinaryTreeNode r3=new BinaryTreeNode(3);
// BinaryTreeNode r4=new BinaryTreeNode(4);
// BinaryTreeNode r5=new BinaryTreeNode(5);
// BinaryTreeNode r6=new BinaryTreeNode(6);
//
// r1.left=r2;
// r1.right=r3;
// r2.left=r4;
// r2.right=r5;
// r3.right=r6;
BinaryTree_Summary bt=new BinaryTree_Summary();
// bt.preOrder(r1);
// bt.inorderTraversal(r1);
// bt.postOrderTraversal(r1);
// bt.levelTraversal(r1);
// bt.levelTaversalRec(r1);
/*
10
/
6 14
/
4 8 16
/
0
*/
BinaryTreeNode r1 = new BinaryTreeNode(10);
BinaryTreeNode r2 = new BinaryTreeNode(6);
BinaryTreeNode r3 = new BinaryTreeNode(14);
BinaryTreeNode r4 = new BinaryTreeNode(4);
BinaryTreeNode r5 = new BinaryTreeNode(8);
BinaryTreeNode r6 = new BinaryTreeNode(16);
BinaryTreeNode r7 = new BinaryTreeNode(0);
r1.left = r2;
r1.right = r3;
r2.left = r4;
r2.right = r5;
r3.right = r6;
r4.left = r7;
BinaryTreeNode ret=bt.convert2LinkedListRec(r1);
while (ret !=null) {
System.out.print(ret.data+" ");
ret=ret.right;
}
// BinaryTreeNode ret1=bt.convert2LinkedList(r1);
// while (ret1 !=null) {
// System.out.print(ret1.data+" ");
// ret1=ret1.right;
// }
// while (ret1 !=null) {
// System.out.print(ret1.data+" ");
// ret1=ret1.left;
// }
}
//1.创建二叉树
public BinaryTreeNode createTree(BinaryTreeNode root){
int data;
Scanner scanner = new Scanner(System.in);
data = scanner.nextInt();
root=new BinaryTreeNode();//创建根节点
root.data=data;
root.left=createTree(root.left);//递归,创建左子树
root.right=createTree(root.right);//递归,创建右子树
return root; //返回树的根节点
}
//2.求二叉树镜像,递归
public void mirrorRec(BinaryTreeNode root){
if (root==null) {
return;
}
if ((root.left==null) &&(root.right==null)){
return;
}
BinaryTreeNode temp=root.left; //交换左右孩子
root.left=root.right;
root.right=temp;
mirrorRec(root.left);
mirrorRec(root.right);
}
//2.求二叉树镜像,迭代
//3.求二叉树节点数,递归----null返回0,然后把左右子树的size加上即可
public int getNodeNumRec( BinaryTreeNode root) {
if (root ==null) {
return 0;
}
return getNodeNumRec(root.left) + getNodeNumRec(root.right)+1;
}
//3.求二叉树节点数,迭代---基本思想同LevelOrderTraversal, 即用一个Queue,在Java里面可以用LinkedList来模拟
public int getNodeNum(BinaryTreeNode root) {
if (root==null) {
return 0;
}
Queue<BinaryTreeNode> que=new LinkedList<BinaryTreeNode>();
que.offer(root); //根节点入队
int cnt=0; //节点数目
while (!que.isEmpty()) {
BinaryTreeNode node=que.poll();//不为空,出队列
cnt++; //出一个,计一个
if (node.left!=null) { //先左后右入队
que.offer(node.left);
}
if (node.right!=null) {
que.offer(node.right);
}
}
return cnt;
}
//4.求二叉树深度,递归
public int getDepthRec(BinaryTreeNode root) {
if (root ==null) {
return 0;
}
int depthleft=getDepthRec(root.left);
int depthright=getDepthRec(root.left);
return depthleft > depthright? (depthleft+1):(depthright+1);
}
//4.求二叉树深度,迭代
public int getDepth(BinaryTreeNode root) {
if (root==null) {
return 0;
}
BinaryTreeNode dum=new BinaryTreeNode(); // 使用DummyNode来区分不同的层
Queue<BinaryTreeNode> que=new LinkedList<BinaryTreeNode>();
que.offer(root); //根节点入队
que.offer(dum);
int depth=-1;
while (!que.isEmpty()) {
BinaryTreeNode node=que.poll();
if (node==dum) { //层结束标志,深度+1
depth++;
if (!que.isEmpty()) { // 如果下一层不是为空,则应该在尾部加DummyNode.
que.offer(dum);
}
}
if (node.left!=null) {
que.offer(node.left);
}
if (node.right!=null) {
que.offer(node.right);
}
}
return depth;
}
//5.前序遍历,递归
public void preOrderRec(BinaryTreeNode root) {
if (root==null) {
return;
}
System.out.print(root+" ");
preOrderRec(root.left);
preOrderRec(root.right);
}
//5.迭代,前序遍历---把根节点存在stack中。
public void preOrder(BinaryTreeNode root) {
if (root==null) {
return;
}
Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
stack.push(root); //根节点入栈
while (!stack.isEmpty()) {
BinaryTreeNode node=stack.pop();
System.out.print(node.data+" ");//输出节点
// 先压入右节点,再压入左节点,这样就可以先弹出左节点。
if (node.right!=null) {
stack.push(node.right);
}
if (node.left!=null) {
stack.push(node.left);
}
}
System.out.println();
}
//6.中序遍历 ,递归
public void inorderTraversalRec(BinaryTreeNode root) {
if (root==null) {
return;
}
inorderTraversalRec(root.left);
System.out.print(root.data+" ");
inorderTraversal(root.right);
}
/**
* 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内,
* 然后输出栈顶元素,再处理栈顶元素的右子树
* http://www.youtube.com/watch?v=50v1sJkjxoc
*
* 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上
* http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
*/
//6.迭代,中序遍历
public void inorderTraversal(BinaryTreeNode root) {
if (root==null) {
return;
}
Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
BinaryTreeNode node=root;
while (true) {
// 把当前节点的左节点都push到栈中
while (node!=null) {
stack.push(node);
node=node.left;
}
if (stack.isEmpty()) {
break;
}
// 因为此时已经没有左孩子了,所以输出栈顶元素
node=stack.pop();
System.out.print(node.data+" ");
// 处理右子树
node=node.right; //再处理右节点
}
System.out.println();
}
//7.后序遍历 ,递归
public void postOrderTraversalRec(BinaryTreeNode root) {
if (root==null) {
return;
}
postOrderTraversalRec(root.left);
postOrderTraversalRec(root.right);
System.out.print(root.data+" ");
}
/**
* 后序遍历迭代解法
* http://www.youtube.com/watch?v=hv-mJUs5mvU
* http://blog.csdn.net/tang_jin2015/article/details/8545457
* 从左到右的后序, 与从右到左的前序的逆序是一样的, 用另外一个栈进行翻转即可
*/
//7.迭代,后序遍历
public void postOrderTraversal(BinaryTreeNode root) {
if (root==null) {
return;
}
Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
Stack<BinaryTreeNode> stack2=new Stack<BinaryTreeNode>();//翻转
stack.push(root); //根节点入栈
while (!stack.isEmpty()) {
BinaryTreeNode node=stack.pop();
stack2.push(node); //这里跟前序不一样,不打印,而是存到stack2中
//先左后右,从右到左的前序 逆序
if (node.left!=null) {
stack.push(node.left);
}
if (node.right!=null) {
stack.push(node.right);
}
}
//弹出stack2中的元素,即从右往左前序遍历的逆序
while (!stack2.isEmpty()) {
System.out.print(stack2.pop().data+" ");
}
System.out.println();
}
//8.层次遍历 ,递归
public void levelTaversalRec(BinaryTreeNode root) {
ArrayList<ArrayList<Integer>> list=new ArrayList<ArrayList<Integer>>();
levelTaversalVisitRec(root,0,list); //递归调用
System.out.print(list); //打印遍历结果
}
private void levelTaversalVisitRec(BinaryTreeNode root, int level,
ArrayList<ArrayList<Integer>> list) {
// TODO Auto-generated method stub
if (root==null) {
return;
}
if (level >= list.size()) { // 如果ArrayList的层数不够用, 则新添加一层
list.add(new ArrayList<Integer>());
}
list.get(level).add(root.data);// visit 当前节点
levelTaversalVisitRec(root.left, level+1, list);// 将左子树, 右子树添加到对应的层。
levelTaversalVisitRec(root.right, level+1, list);
}
/*
* 迭代,层次遍历二叉树(按层次从上往下,从左往右)迭代
* 其实就是广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点
* ,访问,若左子节点或右子节点不为空,将其压入队列
* */
//8.迭代,层次遍历 ---按层次从上往下,从左往右
public void levelTraversal(BinaryTreeNode root) {
Queue<BinaryTreeNode> que=new LinkedList<BinaryTreeNode>();
que.offer(root); //根节点入队
while(!que.isEmpty()){
BinaryTreeNode node=que.poll();
System.out.print(node.data+" ");
if (node.left!=null) { //队列是先进先出,所以要左孩子先进
que.offer(node.left);
}
if (node.right!=null) {
que.offer(node.right);
}
}
System.out.println();
}
//9.由前序和中序遍历序列,重建二叉树
public BinaryTreeNode rebuildTreeRec(List<Integer> pre,List<Integer> in) {
if (pre==null || in==null) {
return null;
}
if (pre.size()==0 || in.size()==0) {
return null;
}
//根节点是前序的第一个元素
BinaryTreeNode root=new BinaryTreeNode(pre.get(0));
// 获得在 inOrder中,根的位置 ,也是左子树节点的个数
int rootIndex=in.indexOf(pre.get(0));
List<Integer> preLeft =pre.subList(1, rootIndex+1);// [ )
List<Integer> preRight =pre.subList(rootIndex+1, pre.size());
List<Integer> inLeft =in.subList(0, rootIndex);
List<Integer> inRight =in.subList(rootIndex+1, in.size());
// 通过 Rec来调用生成左右子树。
root.left =rebuildTreeRec(preLeft, inLeft);
root.right=rebuildTreeRec(preRight, inRight);
return root;
}
//10.推荐递归,将 二叉查找树 变为有序的双向链表,不能创建新节点,只调整指针。
/**
* 查找树的结点定义如下:
以中序遍历二叉搜索树时,其遍历的结点就是有序的。
将根结点的左子树和右子树转换为有序的双向链表,
然后根节点的left指针指向左子树结果的最后一个结点,
同时左子树最后一个结点的right指针指向根节点;
根节点的right指针指向右子树结果的第一个结点,
同时右子树第一个结点的left指针指向根节点。
* */
public BinaryTreeNode convert2LinkedListRec (BinaryTreeNode root) {
return convert2LinkedListRecHelper(root)[0];//最小的节点即是链表的头
}
private BinaryTreeNode[] convert2LinkedListRecHelper(BinaryTreeNode root) {
// TODO Auto-generated method stub
BinaryTreeNode[] ret=new BinaryTreeNode[2];
/*
* 临时变量
* ret[0] 代表左指针
* ret[1] 代表右指针
* */
ret[0]=null;
ret[1]=null;
if (root==null) {
return ret;
}
if (root.left !=null) {
BinaryTreeNode[] left= convert2LinkedListRecHelper(root.left);
left[1].right =root; // 调整关系,将左子树的尾节点(即返回子树的右left[1])连接到根
root.left =left[1];
ret[0] =left[0]; //最小的节点,左
}else {
ret[0]=root; // 左节点返回当前节点root.
}
if (root.right !=null) {
BinaryTreeNode[] right= convert2LinkedListRecHelper(root.right);
right[0].left = root; // 调整关系,将右子树的头节点(即返回子树的左left[0])连接到根
root.right = right[0];
ret[1] = right[1]; //最大的节点,右
}else {
ret[1] = root; // 右节点返回当前节点root.
}
return ret;
}
//10.不推荐迭代,溢出,将二叉查找树变为有序的双向链表,不能创建新节点,只调整指针。
//类似inOrder traversal的做法
public BinaryTreeNode convert2LinkedList (BinaryTreeNode root) {
while (root==null) {
return null;
}
BinaryTreeNode pre =null;
Stack<BinaryTreeNode> stack =new Stack<BinaryTreeNode>();
BinaryTreeNode node=root;
BinaryTreeNode head=null; // 链表头
while (true) {
while (node !=null) {
stack.push(node);
node =node.left;
}
if (stack.isEmpty()) {
break;
}
node =stack.pop();
if (head==null) {
head=node;
}
node.left=pre;
if (pre !=null) {
pre.right=node;
}
node=node.right;
pre=node;
}
return root;
}
//11. 判断二叉树是不是完全二叉树
}
最后
以上就是现代小猫咪为你收集整理的二叉树 面试 JAVA的全部内容,希望文章能够帮你解决二叉树 面试 JAVA所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复