Java数据结构--二叉树的先序中序后序遍历(递归、非递归)
http://www.tuicool.com/articles/Yz2QJn
输出二叉树中所有从根结点到叶子结点的路径: http://blog.csdn.net/htyurencaotang/article/details/12402369
求二叉树中根结点到某结点的路径 (Accepted) :http://blog.sina.com.cn/s/blog_9d754e3e01014uwo.html
数据结构--二叉树--输出树中从根到每个叶子节点的路径(树遍历算法的应用): http://blog.csdn.net/wangrunmin/article/details/7830794
leetcode235 二叉搜索树中寻找最小的公共父节点: http://blog.csdn.net/xudli/article/details/46838747
leetcode236 二叉树中寻找最小的公共父节点:
方法1 找到到两点的路径,然后比较路径即可;
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null||root==p||root==q) return root; //寻找到达两个点的路径 List<TreeNode> pathp = findPath(root,p); List<TreeNode> pathq = findPath(root,q); int len = Math.min(pathp.size(),pathq.size()); int i =0; for( ; i < len ; i++){ if(pathp.get(i)!=pathq.get(i)) break; } return pathp.get(i-1); } //寻找到达某个节点的路径 public static List<TreeNode> findPath(TreeNode root, TreeNode p) { List<TreeNode> ls = new ArrayList<TreeNode>(); Stack<TreeNode> st = new Stack<TreeNode>(); Stack<Boolean> flag = new Stack<Boolean>(); st.push(root); flag.push(false); while (!st.isEmpty()) { TreeNode temp = st.peek(); ls.add(temp); if(temp==p){ //如果已经找到了这个点 break; } if(flag.pop()==true){ st.pop(); ls.remove(ls.size()-1); //因为又添加了一遍,所以要删除两遍 ls.remove(ls.size()-1); continue; } else flag.push(true); if (temp.right != null){ st.push(temp.right); flag.push(false); } if (temp.left != null){ st.push(temp.left); flag.push(false); } } return ls; }
方法2 递归处理
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode 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; return left!=null ? left : right; }
leetcode108 Convert Sorted Array to Binary Search Tree (用排好序的数组构建二叉搜索树)
leetcode109 Convert Sorted List to Binary Search Tree (用排好序的链表构建二叉搜索树) 法1 转换成哈希表,然后同108; 法2 递归处理
leetcode114 Flatten Binary Tree to Linked List 将二叉树转换成链表
leetcode95 Unique Binary Search Trees II 将所有不同的二叉搜索树存到list中
leetcode99 Recover Binary Search Tree 复原二叉搜索树(有两个元素被交换了从而不符合二叉搜索树的定义)
方法:利用中序遍历的思想,二叉搜索树的中序遍历序列是从小到大的。
TreeNode firstele = null; TreeNode secondele = null; TreeNode prevElement = new TreeNode(Integer.MIN_VALUE); //采用先序遍历,找到第一个不符合顺序要求的 public void recoverTree(TreeNode root) { helper(root); int temp = firstele.val; firstele.val = secondele.val; secondele.val = temp; } //中序遍历的思想 public void helper(TreeNode root){ if(root==null) return ; helper(root.left); //寻找第一个不符合顺序要求的 if(firstele == null && prevElement.val >= root.val){ firstele = prevElement; } //寻找第二个不符合顺序要求的 if(firstele != null && prevElement.val >= root.val){ secondele = root; } prevElement = root; helper(root.right); }
leetcode124 Binary Tree Maximum Path Sum 二叉树最大路径和(起点,终点,根均不确定)
方法:利用深度优先搜索,递归求出以每一个节点为根的最大路径
public int solu = Integer.MIN_VALUE; public int maxPathSum(TreeNode root) { helper(root); return solu; } public int helper(TreeNode root){ if(root==null) return 0; int ls = helper(root.left); int rs = helper(root.right); if(ls<0) ls = 0; if(rs<0) rs = 0; int curr = ls+rs+root.val; if(curr>solu) solu = curr; return root.val+Math.max(ls, rs); }
leetcode222 Count Complete Tree Nodes 求完全二叉树节点数量
方法:原来打算遍历一遍计算节点数,超时。另一种方法,递归,计算每个节点一直向左和一直向右的高度。如果高度相等,则为满二叉树,数量为2^h-1,否则递归求左子树和右子树的数量,二者和+1即为完全二叉树节点数
public static int countNodes(TreeNode root){ if(root==null) return 0; int hl = getlefth(root); int hr = getrighth(root); if(hl==hr) return (2<<(hl-1))-1; else return countNodes(root.left)+countNodes(root.right)+1; } public static int getlefth(TreeNode root){ int h = 0 ; TreeNode currnode = root; while(currnode!=null){ currnode= currnode.left; h++; } return h; } public static int getrighth(TreeNode root){ int h = 0 ; TreeNode currnode = root; while(currnode!=null){ currnode= currnode.right; h++; } return h; }
先序遍历 非递归
// 先序遍历 public static List<Integer> preorderTraversal(TreeNode root) { List<Integer> ls = new ArrayList<Integer>(); if (root == null) return ls; Stack<TreeNode> st = new Stack<TreeNode>(); st.push(root); while (!st.isEmpty()) { TreeNode temp = st.pop(); ls.add(temp.val); if (temp.right != null){ st.push(temp.right); } if (temp.left != null){ st.push(temp.left); } } return ls; }
中序遍历 非递归
public void kthSmallest(TreeNode root) { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode temp = root ; while(temp!=null||!stack.isEmpty()){ if(temp!=null){ //左子树入栈 stack.add(temp); temp = temp.left; }else{ temp = stack.pop(); temp = temp .right; } } // while(temp!=null||!stack.isEmpty()){ // while(temp!=null){ //左子树入栈 // stack.add(temp); // temp = temp.left; // } // temp = stack.pop(); // System.out.println(temp.val); // temp = temp.right; // } }
后序遍历 非递归
(和先序遍历有类似的地方)
public static ArrayList<Integer> postorderTraversal2(TreeNode root) { ArrayList<Integer> solu = new ArrayList<Integer>(); Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode curr = root; //指向当前要访问的节点 TreeNode pre = null; //指向前一个被访问的节点 while(curr!=null||!stack.isEmpty()){ if(curr!=null){ stack.push(curr); curr = curr.left; }else{ curr = stack.peek(); //如果当前节点的右节点已没有访问 且 不为空,则将右节点加入到stack if(curr.right!=null && curr.right!=pre){ curr = curr.right; }else{ //否则,说明该节点为最右边,或者它的右边均已访问,应该访问此节点。 solu.add(curr.val); pre = curr; stack.pop(); curr = null; } } } return solu; }
另一种写法;
public static ArrayList<Integer> postorderTraversal(TreeNode root) { ArrayList<Integer> solu = new ArrayList<Integer>(); Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode curr = root; //指向当前要访问的节点 TreeNode pre = null; //指向前一个被访问的节点 while(curr!=null||!stack.isEmpty()){ while(curr!=null){ stack.push(curr); curr = curr.left; } curr = stack.peek(); //如果当前节点的右节点已被访问或者为空,则访问该节点 if(curr.right==null || curr.right==pre){ solu.add(curr.val); pre = curr; stack.pop(); curr = null; }else{ //否则,访问该节点的右孩子 curr = curr.right; } } return solu; }
Morrlis遍历二叉树,时间复杂度O(n),空间复杂度O(1)
详细:http://blog.csdn.net/mxw976235955/article/details/39829973
http://blog.sina.com.cn/s/blog_62d12d690101fdad.html
中序遍历
while 没有结束
如果当前节点有左后代
找到左后代的最右节点,且使最右节点的右指针指向当前节点
转向左后代节点
否则
访问该节点
转向右节点
代码:
public void MorrisInorder(TreeNode root){ TreeNode p = root; TreeNode temp ; while(p!=null){ if(p.left!=null){ temp = p.left; while(temp.right!=null && temp.right!=p){ temp = temp.right; } if(temp.right == null){ temp.right = p; p = p.left; }else{ //temp.right = p System.out.println(p.val); temp.right = null; p = p .right; } }else{ System.out.println(p.val); p = p.right; } } }
先序遍历:和中序遍历只有一处不同
public void MorrisPreorder(TreeNode root){ TreeNode p = root; TreeNode temp ; while(p!=null){ if(p.left!=null){ temp = p.left; while(temp.right!=null && temp.right!=p){ temp = temp.right; } if(temp.right == null){ System.out.print(p.val); //和中序遍历唯一不同的地方,先序遍历第一次碰到开始的节点就输出。 temp.right = p; p = p.left; }else{ //temp.right = p //System.out.print(p.val); temp.right = null; p = p .right; } }else{ System.out.print(p.val); p = p.right; } } }

浙公网安备 33010602011771号