二叉树 面试 JAVA

来源:互联网 发布:照片打印排版软件 编辑:程序博客网 时间:2024/05/03 06:17
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) {   //层结束标志,深度+1depth++; 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 stubif (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 stubBinaryTreeNode[] 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. 判断二叉树是不是完全二叉树}

0 0