非递归实现二叉树的中序遍历

1. 二叉搜索树 (binary search tree)

对于树中的每个节点,若其左子树存在,则其左子树上每个节点的值都不大于该节点的值;若其右子树存在,则其右子树上每个节点的值都不小于该节点的值

查询复杂度:树的高度越低,节点的查询时间复杂度越低,范围为O(logn) ~ O(n)。

2. 二叉搜索树迭代器 (binary search tree iterator) (中序遍历)

1)思路:

  • 最小的第一个点,就是树最左边的点。
  • 二叉树节点在中序遍历中的下一个节点:右子树的最左点 或 路径中最近一个通过左子树包含当前点的点。

2)代码实现:

实现方式一(保存根节点到当前节点的整条路径,每次移除栈顶节点时,都要找到下一个节点,并放入根节点到其的整条路径):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class BSTIterator {
    Stack<TreeNode> stack;

    public BSTIterator(TreeNode root) {
        stack = new Stack<TreeNode>();
        findMostLeft(root);
    }
    
    public int next() {
        //保存当前节点,最后返回该节点
        TreeNode cur = stack.peek();
        //若当前节点的右子树为空,则下一个节点是栈中最近的通过左子树包含该节点的点
        TreeNode node = cur;
        if(node.right == null){
            node = stack.pop();
            while(!stack.isEmpty() && stack.peek().right == node){
                node = stack.pop();
            }
        }else{
        //若当前节点的右子树非空,则把右子树中所有左边的点放入栈中
            findMostLeft(node.right);
        }
        return cur.val; 
    }
    
    public boolean hasNext() {
        if(stack.isEmpty()){
            return false;
        }
        return true;
    }
     
    //将当前树中的左边节点都放入栈中
    private void findMostLeft(TreeNode node){
        while(node != null){
            stack.push(node);
            node = node.left;
        }
    }
}

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator obj = new BSTIterator(root);
 * int param_1 = obj.next();
 * boolean param_2 = obj.hasNext();
 */

实现方式二 (未保存搜索到此节点的路径,每当寻找下一个节点前,都弹出当前节点。)

class BSTIterator {
    //用一个栈来保存BST的待搜索节点
    Stack<TreeNode> stack;

    public BSTIterator(TreeNode root) {
        stack = new Stack<TreeNode>();
        findMostLeft(root);
    }
    
    public int next() {
        //弹出当前节点
        TreeNode node = stack.pop();
        //若该节点有右子树,则把右子节点和右子树上所有最左边节点依次放入栈中
        //若该节点无右子树,则无操作,相当于回到其父节点
        if(node.right != null){
            findMostLeft(node.right);
        }
        return node.val;
    }
    
    public boolean hasNext() {
        if(stack.isEmpty()){
            return false;
        }
        return true;
    }

    //把当前节点及其所有最左边节点依次放入栈中
    private void findMostLeft(TreeNode node){
        while(node != null){
            stack.push(node);
            node = node.left;
        }
    }
}

3. 深拷贝

1) 拷贝数组

int[] list1 = {7,8,9};
int[] list2 = new int[3];
System.arraycopy(list1,0,list2,0,list1.length);
// System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
/* src: 原数组
   srcPos: 拷贝原数组的起始位置
   dest: 目标数组
   destPos: 目标数组的起始位置
   length: 要copy的数组的长度
*/

list1[0] = 10;
list2[1] = 15;
System.out.println(Arrays.toString(list1) + Arrays.toString(list2));
//控制台打印出 [10,8,9][7,15,9]

2) 栈Stack的常用api

// stack的常用方法
//1.初始化
Stack<Object> stack=new Stack<>();

//2.判断是否为空
isEmpty()

//3.添加元素,push和add方法实际最终调用的是同一个方法
push(E item)
add(E item)

//4.获取栈顶值,元素不出栈(栈为空时抛异常)
peek()

//5.查看栈中是否存在obj
// 返回值为int,若存在,返回值为obj距离栈顶的位置;若不存在,返回-1
search(Object obj)

//6.移除栈顶元素,并且返回值是移除的元素
pop()

//其他方法
//7.获取stack长度
size()
//8.下标处添加
add(int index, E element)
//9.添加集合
addAll(Collection<? extends E> c)
//10.移除对象
remove(Object obj)
//11.根据下标移除对象
remove(int index)
//12.清空
clear()

4. 相关例题

LeetCode: 剑指 Offer II 055. 二叉搜索树迭代器

LintCode: 900 · 二叉搜索树中最接近的值, 901 · 二叉搜索树中最接近的值 II

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值