美文网首页
6.二叉树的遍历、翻转二叉树

6.二叉树的遍历、翻转二叉树

作者: LucXion | 来源:发表于2022-01-06 11:33 被阅读0次

根据节点访问顺序的不同,常见的二叉树遍历方式有4种。

前序遍历(Preorder Traversal)

树状结构打印

  • 先访问根节点,前序遍历左子树,前序遍历右子树
    func PreorderTraversal(){
        self .PreorderTraversalNote(note: root)
    }
    func PreorderTraversalNote(note:Note?){
        // 打印当前值
        print(note?.value ?? "")
        // 先遍历左子树
        if let leftNote = note?.leftNote {
            PreorderTraversalNote(note: leftNote)
        }
        // 再遍历右子树
        if let rightNote = note?.rightNote {
            PreorderTraversalNote(note: rightNote)
        }
        // 无子树,中止调用
    }

中序遍历(Inorder Traversal)

根节点在中间,左右子树的先后顺序可变

二叉搜索树按序处理节点

  • 中序遍历左子树,根节点,中序遍历右子树(二叉搜索树的访问结果为从小到大)

  • 中序遍历右子树,根节点,中序遍历左子树(二叉搜索树的访问结果为从大到小)

    func InorderTraversal(){
        InorderTraversalNote(note: root)
    }
    func InorderTraversalNote(note:Note?){
        // 先遍历左子树
        if let leftNote = note?.leftNote {
            InorderTraversalNote(note: leftNote)
        }
        // 打印当前值
        print(note?.value ?? "")
        // 再遍历右子树
        if let rightNote = note?.rightNote {
            InorderTraversalNote(note: rightNote)
        }
        // 无子树,中止调用
    }

后序遍历(Postorder Traversal)

根节点在最后

先子后父的操作

  • 后序遍历左子树,后序遍历右子树,根节点

层序遍历(Level Order Traversal)

从上到下,从左到右,一层一层访问

计算二叉树高度、判断一棵树是否为完全二叉树

    func LevelOrderTraversal(){
        // 通过队列来实现,按层入队,节点出队,对应的子节点入队
        let queue = NSMutableArray.init()
        var tempNote:Note
        queue.add(root!)
        // 遍历,如果下一层还有元素,那就继续遍历
        while(queue.count > 0){
            tempNote = queue.firstObject as! BinarySearchTree.Note
            print(tempNote.value)
            // 打印出首个,入队它的子树
            queue.removeObject(at: 0)
            if let leftNote = tempNote.leftNote {
                queue.add(leftNote)
            }
            if let rightNote = tempNote.rightNote {
                queue.add(rightNote)
            }
        }
    }

树的高度

// 通过递归获取树的高度
    func recursionGetHeight()->Int {
        return recursionGetHeightWithNote(note: root)
    }
    func recursionGetHeightWithNote(note:Note?)->Int{
        if(note == nil){
            return 0
        }
        // 当前节点的高度为最大子节点高度 + 1
        return 1 + max(recursionGetHeightWithNote(note: note?.leftNote), recursionGetHeightWithNote(note: note?.rightNote))
    }

// 通过层序遍历的方式获取树的高度
func height()->Int{
        guard root != nil else { return 0 }
        // 通过队列的方式来层序遍历
        let queue = NSMutableArray.init()
        queue.add(root!)
        // 当前层数,因为以根节点开始,层数默认为1
        var height = 1
        // 当层节点个数
        var levelOrderElement = 1
        while(queue.count > 0){
            // 移除第一个节点,将子节点添加
            let note:Note = queue.firstObject as! Note
            // 层序遍历
            queue.removeObject(at: 0)
            // 当前层数节点数 - 1
            levelOrderElement -= 1
            if let leftNote = note.leftNote {
                queue.add(leftNote)
            }
            if let rightNote = note.rightNote {
                queue.add(rightNote)
            }
            if(levelOrderElement == 0 && queue.count > 0){
                // 当前层数节点遍历结束,并且还有下一层节点需要遍历
                height += 1
                // 此时队列中的节点数为下一层节点总数
                levelOrderElement = queue.count
            }
        }
        return height
    }

判断是否为完全二叉树

层序遍历,确定每个节点都满足完全二叉树的特点

/// 判断是否为完全二叉树
    /// - Returns: <#description#>
    func isCompleteTree()->Bool{
        // 空树非完全二叉树
        guard root != nil else { return false }
        
        // 通过队列的方式来层序遍历
        let queue = NSMutableArray.init()
        queue.add(root!)
        /*
         当左右子节点不为空,那么继续层序遍历
         当左子节点不为空,右子节点为空,那么后面的所有节点都是叶子节点①
         当左子节点为空,右子节点也为空,那么后面所有节点都是叶子节点①
         当左子节点为空,右子节点不为空,直接返回失败②
         */
        var allLastLeafNote = false// 后面的节点是否都是叶子节点
        while(queue.count > 0){
            // 移除第一个节点,将子节点添加
            let note:Note = queue.firstObject as! Note
            var leftNull = true// 为空
            var rightNull = true
            // 层序遍历
            queue.removeObject(at: 0)
            if let leftNote = note.leftNote {
                if(allLastLeafNote == true){
                    return false // ①后面的节点应该都是叶子节点,但出现了子节点
                }
                queue.add(leftNote)
                leftNull = false
            }
            if let rightNote = note.rightNote {
                if(allLastLeafNote == true){
                    return false // ①后面的节点应该都是叶子节点,但出现了子节点
                }
                queue.add(rightNote)
                rightNull = false
            }
            if(leftNull == true && rightNull == false){
                return false // ②无左子节点,但是有右子节点
            }else if(leftNull == true && rightNull == true){
                allLastLeafNote = true//无左右子节点,后面都是叶子节点
            }else if(leftNull == false && rightNull == true){
                allLastLeafNote = true//有左子节点无右子节点,后面都是叶子节点
            }
        }
        return true// 顺利遍历结束,全部满足条件
    }

翻转二叉树

所有节点的左右子树交换,关键在于遍历到左右的子节点,且不要重复遍历,所以任何一种遍历方式都可以实现。

相关文章

  • 二叉树

    二叉树 高度 深度真二叉树 满二叉树 完全二叉树 二叉树遍历前序 中序 后序层序遍历 翻转二叉树 递归法...

  • 数据结构与算法之二叉树遍历(七)

    目录 前序遍历中序遍历后序遍历层序遍历遍历方式的选择条件根据遍历结果重构二叉树翻转二叉树计算二叉树的高度判断一棵树...

  • 2019 算法面试相关(leetcode)--树、二叉树、二叉搜

    翻转二叉树二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历验证二叉搜索树二叉树的最近公共祖先二叉搜索树的最近公共祖...

  • 2020-05-25 【翻转二叉树】

    翻转一棵二叉树。 解答 递归 后序遍历 代码: 递归 前序遍历

  • 翻转二叉树(Java)

    翻转二叉树 对于此题而言,我们使用深度优先算法来遍历二叉树。 1、深度优先算法是根据二叉树的路径进行遍历2、广度优...

  • 阿里达摩院常见算法题

    一、二叉树中序遍历 二、二叉树层序遍历 广度优先 三、翻转二叉树 四、反转链表 五、岛屿数量 我们可以将二维网格看...

  • 二叉树 基础操作

    二叉树的使用 二叉树结构 先序创建二叉树 DFS 先序遍历二叉树 中序遍历二叉树 后序遍历二叉树 BFS 层次遍历...

  • swift: 层序遍历翻转二叉树和快速排序

    Talking is cheap, show the codes. 层序遍历进行翻转二叉树 快速排序

  • 二叉树遍历

    二叉树 二叉树的存储结构 前序遍历 中序遍历 后序遍历 遍历代码 反转二叉树 深入学习二叉树 二叉树-你必须要懂!...

  • 226. Invert Binary Tree

    题意:翻转二叉树 思路:后根遍历,很好的练习题; 练习指数:5

网友评论

      本文标题:6.二叉树的遍历、翻转二叉树

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