阅读 88

Swift 刷题 二叉树的前中后三种遍历

二叉树

二叉树的遍历分成以下四种

题目:求某一个二叉树的前中后三种遍历

对于任意一树型结构来说,他的前后中的遍历主要取决于它根节点的位置,对于任意一子树的来说也一样。那么基于递归来说,由于树的左右结点可能成为其子树的根节点,那么 中→左→右 左→中→右 左→右→中 中的的位置就是我们需要打印的位置。

//Definition for a binary tree node.
public class TreeNode {
    public var val: Int
    public var left: TreeNode?
    public var right: TreeNode?
    public init(_ val: Int) {
        self.val = val
        self.left = nil
        self.right = nil
    }
}

class Solution {
    var traversals = Array<Int>()
    func treeTraversal(_ root: TreeNode?) -> [Int] {
        guard root != nil else {
            return []
        }   
        return traversals
    }
}
复制代码
递归

对于前中后三种遍历来说,最容易理解的是其递归的实现。

递归步骤一般需要遵循以下三种当是

  1. 确定递归的参数以及返回值
  2. 确定递归的终止条件 递归算法一定有终止条件,避免死循环。
  3. 确定单次递归的逻辑
前序遍历
    /// 前序遍历
    func preorder(_ node: TreeNode?) {
        guard node != nil else {
            return
        }
        traversals.append(node!.val)
        preorder(node?.left)
        preorder(node?.right)
    }
复制代码
中序遍历
    /// 中序遍历
    func inorder(_ node: TreeNode?) {
        guard node != nil else {
            return
        }
        preorder(node?.left)
        traversals.append(node!.val)
        preorder(node?.right)
    }
复制代码
后序遍历
    /// 后续遍历
    func postorder(_ node: TreeNode?) {
        guard node != nil else {
            return
        }
        preorder(node?.left)
        preorder(node?.right)
        traversals.append(node!.val)

    }
复制代码
迭代

二叉树的迭代步骤一般是将节点加入到一个 中,然后通过访问栈头/栈尾,根据顺序访问所有的符合的节点

前序遍历
func preorderIteration(_ root: TreeNode?) {
  var st:[TreeNode?] = [root]
  while !st.isEmpty {
    let node = st.removeFirst()
    if node != nil {
      traversals.append(node!.val)
    }else {
      continue
    }
    st.insert(node?.right, at: 0)
    st.insert(node?.left, at: 0)
  }
}
复制代码
中序遍历
func inorderIteration(_ root: TreeNode?) {
    var st:[TreeNode?] = []
    var cur:TreeNode? = root
    while cur != nil || !st.isEmpty {
        if cur != nil {
            st.insert(cur, at: 0)
            cur = cur?.left
        }else {
            cur = st.removeFirst()
            traversals.append(cur!.val)
            cur = cur?.right
        }
    }
}
复制代码
后序遍历

后序遍历需要最后访问根节点 左→右→中 所以我们可以先访问 中→右→左得到结果后反转变成 左→右→中

func postorderIteration(_ root: TreeNode?) {
    var st:[TreeNode?] = [root]
    while !st.isEmpty {
        let node = st.removeFirst()
        if node != nil {
            print(node!.val)
            traversals.append(node!.val)
        }else {
            continue
        }
        st.insert(node?.left, at: 0)
        st.insert(node?.right, at: 0)
    }
    traversals = traversals.reversed()
}
复制代码
颜色标记法

参照 颜色标记法-一种通用且简明的树遍历方法 这种标记法来实现二叉树的前中后三序遍历。大致就是对已访问的节点进行设置,寻找其未访问的节点。

    func tuple(_ root: TreeNode?) -> [Int] {
        //前序 中左右 按照右左中
        //中序 左中右 按照右中左
        //后序 左右中 按照中右左
        var result = [Int]()
        var statck = [(0, root)]
        while !statck.isEmpty {
            let (isVisted, node) = statck.removeLast()
            if node == nil {
                continue
            }
            if isVisted == 0 {
//                ///前序遍历
//                statck.append((0, node?.right))
//                statck.append((0, node?.left))
//                statck.append((1, node))
//                ///中序遍历
//                statck.append((0, node?.right))
//                statck.append((1, node))
//                statck.append((0, node?.left))
                ///后序遍历
                statck.append((1, node))
                statck.append((0, node?.right))
                statck.append((0, node?.left))
            } else {
                result.append(node!.val)
            }
        }
        return result
    }
复制代码