二叉树相关
1.计算二叉树的高度,两种方式
这里给的是哪些节点连接,所以先处理一下这些节点,把它变为二叉树。
static class Node{ int data; private Node lchild; private Node rchild; Node(int data){ this.data = data; } } public static int GetBTreeDepth(Node node)//递归的思路 { if( node == null ) return 0; int lDepth =GetBTreeDepth(node.lchild); int rDepth =GetBTreeDepth(node.rchild); return ((( lDepth > rDepth )? lDepth: rDepth) + 1 ); } public static int QueueDepth(Node node) //通过队列层次遍历的思路 { if(node==null) return 0; Queue<Node> queue = new LinkedList<Node>(); queue.add(node); int num=0; while(!queue.isEmpty()) { num++; int size=queue.size(); for(int i=0;i<size;i++) { Node temp=queue.poll(); if(temp.lchild!=null) queue.add(temp.lchild); if(temp.rchild!=null) queue.add(temp.rchild); } } return num; } public static void main(String[] args){ Scanner in = new Scanner(System.in); int n=in.nextInt(); Queue<Node> queue = new LinkedList<Node>(); int[][] num=new int[n-1][2]; int[] lable=new int[n-1]; for(int j=0;j<n-1;j++) { num[j][0]=in.nextInt(); num[j][1]=in.nextInt(); } Node head=new Node(1); queue.add(head); while(!queue.isEmpty()) { Node temp=queue.poll(); for(int i=0;i<num.length;i++) { if(num[i][0]==temp.data&&lable[i]==0) { Node left=new Node(num[i][1]); if(temp.lchild==null) temp.lchild=left; else temp.rchild=left; queue.add(left); lable[i]=1; continue; } if(num[i][1]==temp.data&&lable[i]==0) { Node right=new Node(num[i][0]); temp.rchild=right; queue.add(right); lable[i]=1; continue; } } } }
2.计算二叉树的宽度,还是通过队列计算每一层节点的个数
public static int GEtBtreeBith(Node node,int n) { int[] num=new int[n+1]; if(node==null) return 0; Queue<Node> queue = new LinkedList<Node>(); queue.add(node); int i=0; while(!queue.isEmpty()) { i++; int size=queue.size(); num[i]=size; for(int j=0;j<size;j++) { Node temp=queue.poll(); if(temp.lchild!=null) queue.add(temp.lchild); if(temp.rchild!=null) queue.add(temp.rchild); } } int maxLen=0; for(int k=1;k<n+1;k++) { if(num[k]>maxLen) maxLen=num[k]; } return maxLen; }
3.二叉树的先序中序后序的非递归形式
//先序
public static void preOrder(TreeNode head) { Stack<TreeNode> stack=new Stack<>(); if(head!=null) { stack.push(head); while(!stack.isEmpty()) { TreeNode temp=stack.pop(); System.out.print(temp.val+"->"); if(temp.right!=null) stack.push(temp.right); if(temp.left!=null) stack.push(temp.left); } }
}
//中序
public static void inOrder(TreeNode head) { Stack<TreeNode> stack=new Stack<>(); if(head!=null) { TreeNode temp=head; while(!stack.isEmpty()||temp!=null) { while(temp!=null) { stack.push(temp); temp=temp.left; } if(!stack.isEmpty()) { temp=stack.pop(); System.out.print(temp.val+"-"); temp=temp.right; } } } }
//后序
public static void postOrder(TreeNode head) { int flag; //用来表示是否在处理栈顶标志,1就是处理栈顶 Stack<TreeNode> stack=new Stack<>(); TreeNode p; //用来判断是否前一个已经访问的节点 if(head!=null) { TreeNode temp=head; do { while(temp!=null) { stack.push(temp); temp=temp.left; } p=null; flag=1; while(!stack.isEmpty()&&flag==1) { temp=stack.peek(); if(temp.right==p) { System.out.print(temp.val+"-"); stack.pop(); p=temp; } else { temp=temp.right; flag=0; } } } while(!stack.isEmpty()); } }
给定一个数组,判断它是不是 某个二叉排序树的后序遍历的顺序
BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x (也就是根),如果去掉最后一个元素的序列为T,那么T满足:T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两段(子树)都是合法的后序序列。完美的递归定义 : ) 。
public boolean VerifySquenceOfBST(int [] sequence) { if(sequence.length == 0){ return false; } if(sequence.length == 1){ return true; } return judge(sequence,0,sequence.length-1); } public boolean judge(int[] a,int start,int end){ if(start>=end) return true; int root=a[end]; int i=start; while(a[i]<root) { i++; } for(int j=i;j<end;j++) { if(a[j]<root) return false; } return judge(a,start,i-1)&&judge(a,i,end-1); }
4.给定前序和中序,重建二叉树
public static TreeNode reConstructBinaryTree(int[] pre,int[] in) { if(pre.length==0||in.length==0) return null; TreeNode head=new TreeNode(pre[0]); int mid=0; for(int i=0;i<in.length;i++) { if(pre[0]==in[i]) { mid=i; break; } } int[] inleft=Arrays.copyOfRange(in, 0, mid); int[] preleft=Arrays.copyOfRange(pre, 1, mid+1); int[] inright=Arrays.copyOfRange(in, mid+1, in.length); int[] preright=Arrays.copyOfRange(pre, mid+1, pre.length); head.left=reConstructBinaryTree(preleft, inleft); head.right=reConstructBinaryTree(preright, inright); return head; }
5.输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。
深度优先搜索的方式:
private ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>(); private ArrayList<Integer> list = new ArrayList<Integer>(); public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) { if(root == null) return listAll; list.add(root.val); target -= root.val; if(target == 0 && root.left == null && root.right == null) listAll.add(new ArrayList<Integer>(list)); FindPath(root.left, target); FindPath(root.right, target); list.remove(list.size()-1); return listAll;
}
用上面的方法打印从头结点到根节点的最长路径:
int max=0; ArrayList<Integer> list=new ArrayList<>(); public void maxLength(Node head) { if(head==null) return; list.add(head.data); if(head.lchild==null&&head.rchild==null) { int temp=0; for(Integer i:list) { temp+=i; } max=Math.max(temp, max); } maxLength(head.lchild); maxLength(head.rchild); list.remove(list.size()-1); }
6.判断一棵二叉树是不是平衡二叉树
public int getDepth(TreeNode root){ if(root==null) return 0; int left=getDepth(root.left); int right=getDepth(root.right); if(Math.abs(left-right)>1){ isBalanced=false; } return right>left ?right+1:left+1; }
7.二插排序树的第k个节点
通过非递归的中序遍历,在输出的地方加一个计数
8.判断二叉树是不是完全二叉树
思想:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
有如下算法,按层次(从上到下,从左到右)遍历二叉树,当遇到一个节点的左子树为空时,则该节点右子树必须为空,且后面遍历的节点左
右子树都必须为空,否则不是完全二叉树。
public boolean isCompleteBinaryTree(TreeNode head) { if (head == null) return true; boolean lable = false;//是否需要左右孩子都为空的标志 LinkedList<TreeNode> queue = new LinkedList<>(); queue.add(head); while (!queue.isEmpty()) { TreeNode temp = queue.poll(); if (lable) {//需要左右孩子都为空 if (temp.left != null || temp.right != null) return false; } else { if (temp.left != null && temp.right != null) { queue.add(temp.left); queue.add(temp.right); } else if (temp.left != null) {//左孩子不为空,右孩子为空,后面的节点都不能有左右孩子了 queue.add(temp.left); lable = true; } else if (temp.right != null) {//出现了左孩子为空,右孩子不为空的情况,直接返回false return false; } else {//当前节点左右孩子节点都为空,那么后面的节点也必须是这样 lable = true; } } } return true; }
9.求二叉树中叶子节点的个数
public static int LeafNum(TreeNode head) { if(head==null) return 0; if(head.left==null&&head.right==null) return 1; int numLeft=LeafNum(head.left); int numRight=LeafNum(head.right); return numLeft+numRight; }
10.求二叉树的镜像:
public static TreeNode Mirror(TreeNode head){ if(head==null) return null; TreeNode pLeft=Mirror(head.left); TreeNode pRight=Mirror(head.right); head.left=pRight; head.right=pLeft; return head; }
非递归解法:
public void Minor(Node node) //通过队列层次遍历的思路 { if(node==null) return; Queue<Node> queue = new LinkedList<Node>(); queue.add(node); while(!queue.isEmpty()) { int size=queue.size(); for(int i=0;i<size;i++) { Node temp=queue.poll(); System.out.print(temp.data+" "); if(temp.rchild!=null) queue.add(temp.rchild); if(temp.lchild!=null) queue.add(temp.lchild); } System.out.println(); } }
11.求二叉树的直径leetcode543
public int helper(TreeNode root) { if(root==null) return 0; int ldepth=helper(root.left); int rdepth=helper(root.right); max=Math.max(max, ldepth+rdepth); return 1+Math.max(ldepth, rdepth); }
12.二叉查找树的查找和插入(删除太麻烦了)
public TreeNode BSTSearch(TreeNode root,int k) { TreeNode cur=root; if(root==null) return null; else if(cur.val==k) { return cur; }else if(k<cur.val) { return BSTSearch(root.left,k); } else return BSTSearch(root.right,k); } public int BSTInsert(TreeNode root,int k) { TreeNode cur=root; if(cur==null) { cur=new TreeNode(k); cur.left=null; cur.right=null; return 1; } else if(cur.val==k) { return 0;//存在相同的,返回0,不插入 } else if(k<cur.val) { return BSTInsert(cur.left, k); } else return BSTInsert(cur.right, k); }
13.两颗二叉树A,B判断B是不是A的子结构
public boolean HasSubtree(TreeNode root1,TreeNode root2) { if(root1==null||root2==null) return false; return isSubtree(root1, root2)||HasSubtree(root1.left, root2)||HasSubtree(root1.right, root2); } public boolean isSubtree(TreeNode root1,TreeNode root2){ if(root2==null) return true; if(root1==null) return false; if(root1.val==root2.val) return isSubtree(root1.left,root2.left)&&isSubtree(root1.right,root2.right); else return false; }
14.在一个二叉搜索树中,使得当前节点的值等于大于等于它的节点的值的和。
中序遍历中,当前节点后面的节点都是大于当前节点的,所以我们用反向中序遍历
private int mid(Node root,int exp){ if (root == null) { return exp; } int right = mid(root.rchild,exp); root.data += right; int left = mid(root.lchild,root.data); return left; }
非递归写法
private void mid(Node root){ Stack<Node> stack=new Stack<>(); int help=0; if(root!=null) { Node temp=root; while(!stack.isEmpty()||temp!=null) { while(temp!=null) { stack.push(temp); temp=temp.rchild; } if(!stack.isEmpty()) { temp=stack.pop(); temp.data+=help; help=temp.data; System.out.print(temp.data+"-"); temp=temp.lchild; } } } }
15.逆时针打印二叉树的最外面一圈节点
public void printleft(TreeNode root,boolean print) { if(root==null) return; if(print||(root.left==null&&root.right==null)) { System.out.print(root.data+"-"); } printleft(root.left,print);//左边是一定要打的 printleft(root.right,print&&root.left==null?true:false);//左边延伸为空的话打印右分支 return; } public void printright(TreeNode root,boolean print) { if(root==null) return; printright(root.left,print&&root.right==null?true:false);//右分支为空就打印左分支 printright(root.right,print); if(print||(root.left==null&&root.right==null)) System.out.print(root.data+"-"); return; } public void printhead(TreeNode root) { if(root==null) return; System.out.print(root.data+"-"); if(root.left!=null&&root.right!=null) { printleft(root.left,true); printright(root.right,true); } else { printhead(root.left!=null?root.left:root.right); } return; }
https://www.cnblogs.com/PrimeLife/p/5460513.html
16.找任意两个节点的最近公共祖先:
递归:
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { //如果找到 p 或者 q 那么就没有必要接着递归,因为共同祖先只可能是该节点或该节点祖先 //如果 root 为空了,说明这条路径上不可能有 p 或 q 节点,返回空 if(root == null || root == p || root == q) return root; TreeNode left = lowestCommonAncestor(root.left, p, q); //往左分支上寻找 TreeNode right = lowestCommonAncestor(root.right, p, q); //往右分支上寻找 if(left != null && right != null) return root; //说明 p 和 q 是分布在 root 两侧,返回即可 if(left != null) return left; //说明在 left 分支上找到 p 或 q 节点,返回即可 return right; //否则返回 right }
非递归:
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { HashMap<TreeNode, TreeNode> parent = new HashMap<>(); parent.put(root, null); Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while(!parent.containsKey(p) || !parent.containsKey(q)) { //找到 p 和 q 的父节点 root = queue.poll(); if(root != null) { parent.put(root.left, root); parent.put(root.right, root); queue.add(root.left); queue.add(root.right); } } HashSet<TreeNode> set = new HashSet<>(); while(p != null) { //将 p 的所有父节点放入 set 中 set.add(p); p = parent.get(p); } while(!set.contains(q)) { //找到公共父节点就返回 q = parent.get(q); } return q; }
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10702989.html

浙公网安备 33010602011771号