部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

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;
}
View Code

方法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;
}
View Code

 

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);
}
View Code

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);
}
View Code

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;
}
View Code

 

 

先序遍历 非递归

// 先序遍历
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;        
}
View Code

 

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;
        }
    }
}

 

posted @ 2015-07-19 10:41  流了个火  阅读(341)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats