解题思路:
Morris二叉树的中序遍历
Morris 中序遍历算法的基本思路是利用节点的空闲指针,将当前节点的左子树的最右节点的右指针指向当前节点,从而在遍历完当前节点的左子树后,能够通过该指针回到当前节点,进而遍历当前节点和右子树。这样就可以在不使用栈或递归的情况下实现中序遍历
时间复杂度O(2n)
空间复杂度O(1)
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func inorderTraversal(root *TreeNode) (res []int) {//inorder按顺序Traversal遍历
for root != nil {
if root.Left != nil {
// predecessor(前驱)节点表示当前 root 节点向左走一步,然后一直向右走至无法走为止的节点
predecessor := root.Left
for predecessor.Right != nil && predecessor.Right != root {
// 有右子树且没有设置过指向 root,则继续向右走
predecessor = predecessor.Right
}
if predecessor.Right == nil {
// 将 predecessor 的右指针指向 root,这样后面遍历完左子树 root.Left 后,就能通过这个指向回到 root
predecessor.Right = root
// 遍历左子树
root = root.Left
} else { // predecessor 的右指针已经指向了 root,则表示左子树 root.Left 已经访问完了
res = append(res, root.Val)
// 恢复原样
predecessor.Right = nil
// 遍历右子树
root = root.Right
}
} else { // 没有左子树
res = append(res, root.Val)
// 若有右子树,则遍历右子树
// 若没有右子树,则整颗左子树已遍历完,root 会通过之前设置的指向回到这颗子树的父节点
root = root.Right
}
}
return
}