作者: 奉先 | 来源:发表于2021-09-25 08:22 被阅读0次

1. 二叉树的遍历

二叉树的遍历可以有三种 : 先序、 中序、 后序遍历 。先序是根左右 ,中序是左根右 ,后序是左右根。 这三种遍历方式可以使用递归实现,也可以不用递归(自己来压栈代替系统压栈)。

1.1 递归实现

为了记忆方便,可以统一使用 “递归序”来实现三种次序的遍历 。 看如下的代码

public class Traverse {
    public void myTraverse(TreeNode head){
        //process1
        if(head == null ) return;
        //process1
        myTraverse( head.left);
        //process2
        //process2
        myTraverse( head.right);
        //process3
        //process3

    }
}

如果在process1之间,执行代码就是先序遍历,在process2之间,执行代码就是中序遍历,在process3之间,执行代码就是中序遍历,这样代码就非常容易实现了。下面是按照递归序改造的先序遍历在leetcode上执行,因为不是void型返回结果,而是把遍历结果插入到一个list中,所以代码中带了一个list型的参数,但是不影响主体。

class Solution {

    //通过递归序完成先序遍历
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> outPut = new ArrayList<>() ; 
        Traversal(root,outPut) ;
        return outPut ; 
    }

    public void Traversal(TreeNode root, List<Integer> outPut){
        if(root == null) return ;
        outPut.add(root.val) ;
        Traversal(root.left, outPut) ;
        Traversal(root.right, outPut) ;
    }

}

1.2 非递归实现 :

非递归实现三种遍历方式,使用额外栈来实现,这样容易记忆 。

1.2.1 先序遍历 :

先序遍历使用栈,要记住下边几个步骤 :

1.初始化将树的根节点压栈 ;
2.从栈中弹出一个节点 ;
3.开始做遍历操作(例如:打印等等)
4.把这个弹出的节点的子树压栈(先右后左,如果有的话)
5.循环执行 2~3 步骤。

下面是使用 栈完成的非递归前序遍历 :

    //通过非递归序完成先序遍历
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> outPut = new ArrayList<>() ;
        if(root != null){
            Stack<TreeNode> usStack = new Stack() ;
            usStack.push(root);
            while(!usStack.isEmpty()){
                TreeNode cp = usStack.pop();
                outPut.add(cp.val) ;
                if(cp.right != null) usStack.push(cp.right);
                if(cp.left != null) usStack.push(cp.left);
            }

        }
        return outPut;
    }

1.2.2 后序遍历 :

上边前序遍历,使用了一个栈,压栈顺序是根、右、左 ,输出顺序是 根、左、右(也就是前序遍历)。这时,在压栈时,如果我先压左再压右,那么输出顺序就变成了 根、右、 左。
这时,我再使用一个辅助收集栈,输出时候不打印,而是放入收集栈,最后再输出时,就变成了后序遍历了。 相比于前序遍历得到立即打印,这个就变成了都压栈完后,一起打印就得到了后序遍历了。
这样流程就梳理为下边的样子 :

1.初始化将树的根节点压原始栈 ;
2.从原始栈中弹出一个节点,记为cur ;
3.cur压入收集栈
4.把这个cur的子树压入原始栈(先左后右,如果有的话)
5.循环执行 2~4 步骤。
6.将收集栈统一打印。

下边是后序遍历的非递归实现 :

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> outPut = new ArrayList<>() ;
        if(root != null){
            Stack<TreeNode> oriStack = new Stack() ;
            Stack<TreeNode> collectStack = new Stack() ;
            oriStack.push(root);
            while(!oriStack.isEmpty()){
                TreeNode curr = oriStack.pop();
                collectStack.push(curr);
                //原始栈的压栈次序是先左后右,与先序遍历不一样
                if(curr.left != null) oriStack.push(curr.left);
                if(curr.right != null) oriStack.push(curr.right);
            }
            while (!collectStack.isEmpty()){
                outPut.add(collectStack.pop().val);
            }
        }
        return outPut;
    }
}

1.2.3 中序遍历 :

中序遍历的算法有所不同 ,使用一个栈就可以完成。 流程如下 :

1.初始化将树的根节点压栈 ;
2.对于每一棵子树,左边界依次压栈,直到压到为NULL为止。
3.弹出栈顶节点,弹出时打印。
4.对弹出节点的右子树重复,2-3过程。

下面是 中序遍历的java代码实现(非递归):

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> outPut = new ArrayList<>();
        if (root != null) {
            Stack<TreeNode> oriStack = new Stack();
            while(!oriStack.isEmpty() || root !=null){
                if(root != null){
                    oriStack.push(root) ;
                    root = root.left ;
                }
                else
                {
                    root = oriStack.pop() ;
                    outPut.add(root.val) ;
                    root = root.right ;
                }
            }
        }
        return outPut ;
    }
}

2. 搜索二叉树

如何判断一棵树是搜索二叉树 ,要完成这个问题,首先需要了解什么是搜索二叉树 ?

对于一棵搜索二叉树而言,每一个节点的左子树都比右子树小 。也就是说 左子树节点 < 根节点 < 右子树节点。经典的搜索二叉树中没有重复值的节点。

其实比较简单,只要做“中序遍历” 后,得到的序列是单调上升,即可表示是一棵搜索二叉树。

相关文章

  • 水彩过程 | 树树树树

    练习了一下树的画法,用毛笔勾树干,扇形笔画树叶还是又快又方便的。因为不是写实风格,只要把树的意象画出来就可以,所以...

  • 树·树

    ​如果有来生,要做一棵树,站成永恒,没有悲欢姿势,一半在尘土里安详。一半在风里飞扬,一半洒落阴凉,一半沐浴阳光。 ...

  • 树,树……

    树,树…… ——洛尔迦 树,树, 枯了又绿。 脸蛋美丽的姑娘 在那里摘橄榄。 风,塔楼上的求爱者, 拦腰把她...

  • 橄榄树树树

    在建班级群的时候,我顺手打了三个树——橄榄树树树。是的,这是橄榄树第三次起航。 第一次,在北京,我说,我愿意在无人...

  • 树,与树

    (第一次学着简书里文友看图写诗,2020的图,各位讲究着看吧) 文/三少爷的糖 一颗树站在山头 遥望着远方,朦胧中...

  • 树,与树

    我不是一个很喜欢女生哭闹的人。 哭闹,意味着理智被情感摧毁。 理智没了,沟通渠道也就关闭了。 没有了沟通,剩下的就...

  • 树和树

    我的家门前有一棵柏树,不是什么稀罕的树,但它却挺直腰杆儿,坚定的伫立在我家门前,望着远方,似乎在等什么人又不像在等...

  • 树树秋声

    余秋雨说:生命,是一树花开,或安静或热烈,或寂寞或璀璨。日子,就在岁月的年轮中渐次厚重,那些天真的、跃动的、抑或沉...

  • 短篇‖树树

    这是一条幽静的古道,两旁尽是残垣断壁,竟也有一些台阶通向几栋还算有顶篷的石质的建筑物。我和我的伙伴着级上了一段...

  • 树树夜夜

    长夜唧唧夏虫前 长街相对两树闲 冠盖接云皆无语 此缘如可问苍天

网友评论

    本文标题:

    本文链接:https://www.haomeiwen.com/subject/pwotnltx.html