二叉树的遍历,首先是写出二叉树的三种常见遍历。

三种常见遍历方法为,前中后,这些遍历方法的定义主要是基于对 Root 节点而言的,前序的定义是首先输出 Root 节点,然后左右子节点。中序的含义是,左 Root 右。后序是,左 右 Root 这个顺序。可以看到,所谓的前中后实际上是 Root 节点的是处在 前、中与后,左右子节点是固定的。

遍历方法 定义极其实现
前序遍历 首先访问 Root, 然后递归调用方法访问左节点,右节点
中序遍历 首先访问左节点,然后访问 Root ,再然后访问右节点
后序遍历 首先访问左节点,然后右节点,然后是 Root

树的构造,我这了是生成随机数然后判断是否为 偶数 ,然后赋值给左节点或者右节点的,这种方式构造的树只会在一支上延伸下去。

树节点代码以及三种遍历:

class TreeNode constructor(val value: Int) {
    // 二叉树的定义,拥有左右子树
    var left: TreeNode? = null
    var right: TreeNode? = null

    companion object {
        // 前序遍历,优先跟节点,然后左,然后右
        fun preOrderPrint(r: TreeNode?, list:MutableList<Int>) {
            if (r == null) {
                return
            }
            list.add(r.value)
            ALGPrint("pre order is: $r ")
            preOrderPrint(r.left, list)
            preOrderPrint(r.right, list)
        }

        // 中序遍历,优先左节点,然后跟节点,最后右节点
        fun inOrderPrint(root: TreeNode?, list: MutableList<Int>) {
            if (root == null) {
                return
            }
            inOrderPrint(root.left, list)
            list.add(root.value)
            ALGPrint("in order: $root")
            inOrderPrint(root.right, list)

        }

        // 后序遍历,优先左节点,然后右节点,最后根节点
        fun postOrderPrint(root: TreeNode?, list: MutableList<Int>) {
            if (root == null) {
                return
            }
            postOrderPrint(root.left, list)
            postOrderPrint(root.right, list)
            list.add(root.value)
            ALGPrint("in order: $root")
        }
    }

    override fun toString(): String {
        return "current : $value left : ${left?.value} right: ${right?.value}"
    }
}

构造树的代码:

    private fun createTreeNode(length: Int): TreeNode {
        val rand = getRandom()
        val root = TreeNode(rand.nextInt(100))
        var p = root
        var isRoot = true
        ALGPrint("root is : $root")
        repeat(length) {
            val num = rand.nextInt(2000)
            if (num % 2 == 0) {
                p.left = TreeNode(num)
            } else {
                p.right = TreeNode(num)
            }

            var next = rand.nextInt(2000)
            if (next == num) {
                next = num + 1
            }
            ALGPrint("it is $it : num is $num ------- next $next")

            val bb = rand.nextInt(3)
            // 这里是增加左右节点,为了构造二叉树,否则不会有俩个叉子,增加这个就会比传入的 length 长
            if (isRoot || (bb != 0 && next % bb == 0)) {
                isRoot = false
                if (p.right == null) {
                    p.right = TreeNode(next)
                } else if (p.left == null) {
                    p.left = TreeNode(next)
                }
            }

            p = setLeftOrRight(next % 2 == 0, p)

        }
        return root
    }

    private fun setLeftOrRight(isFirstLeft: Boolean, root: TreeNode?) : TreeNode{
        var p : TreeNode? = root
        var isSet = false
//        ALGPrint("is first left: $isFirstLeft p is $p")
        if (isFirstLeft) {
            if (p?.left != null) {
                isSet = true
                p = p.left!!
            }
            if (!isSet && p?.right != null) {
                p = p.right!!
            }
        } else {
            if (p?.right != null) {
                isSet = true
                p = p.right!!
            }
            if (!isSet && p?.left != null) {
                p = p.left!!
            }
        }
        return p!!
    }

二叉树非递归遍历:

        // 使用 while 循环对树进行遍历
        fun testPreOrderUseLoop(root: ALGTreeNode?, list: LinkedList<Int>) {
            if (root == null) {
                return
            }

            val s = Stack<ALGTreeNode>()
            var rt : ALGTreeNode? = root
            while (rt != null || !s.isEmpty()) {
                while (rt != null) {
                    // 这里放进去值,不是从 s 里面遍历再放进 list
                    list.add(rt.value)
                    // 基本思路是,一路往左走,撞了南墙(碰到NULL)就回头;
                    // 回头摆到右(子树的根),接着往左走(循环)
                    s.push(rt)
                    rt = rt.left
                }
                if (!s.isEmpty()) {
                    rt = s.pop()
                    rt = rt.right
                }
            }
        }