算法学习记录(二十五)

95 阅读1分钟

问:

  1. 莫里斯遍历
  2. 莫里斯遍历改先中后序遍历

解:

  1. 流程:①判断当前是否有左节点,没有则当前节点指向右节点;②找到左树的最右节点,若最右节点的右节点为null,将其指向当前节点,当前节点指向左节点;若最右节点的右节点为当前节点,将其重新指向null,当前节点指向右节点
function Morris(root) {
    let curNode = root
    while (curNode) {
        if (curNode.left) {
            let mostRight = curNode.left
            while (mostRight.right && mostRight.right !== curNode) {
                mostRight = mostRight.right
            }
            if (mostRight.right === null) {
                mostRight.right = curNode
                curNode = curNode.left
                continue
            }
            if (mostRight.right === curNode) {
                mostRight.right = null
            }
        }
        curNode = curNode.right
    }
}
  1. 先序:只到达一次的节点直接打印;到达两次的节点,第一次到达时打印
function Morris(root) {
    let curNode = root
    while (curNode) {
        if (curNode.left) {
            let mostRight = curNode.left
            while (mostRight.right && mostRight.right !== curNode) {
                mostRight = mostRight.right
            }
            if (mostRight.right === null) {
                console.log(curNode)
                mostRight.right = curNode
                curNode = curNode.left
                continue
            }
            if (mostRight.right === curNode) {
                mostRight.right = null
            }
        }
        console.log(curNode)
        curNode = curNode.right
    }
}

中序:只到达一次的节点直接打印;到达两次的节点,第二次到达时打印

function Morris(root) {
    let curNode = root
    while (curNode) {
        if (curNode.left) {
            let mostRight = curNode.left
            while (mostRight.right && mostRight.right !== curNode) {
                mostRight = mostRight.right
            }
            if (mostRight.right === null) {
                mostRight.right = curNode
                curNode = curNode.left
                continue
            }
            if (mostRight.right === curNode) {
                mostRight.right = null
            }
        }
        console.log(curNode)
        curNode = curNode.right
    }
}

后序:到达两次的节点,第二次到达时,逆序打印左树的右边界

function Morris(root) {
    let curNode = root
    while (curNode) {
        if (curNode.left) {
            let pre = null
            let mostRight = curNode.left
            while (mostRight.right && mostRight.right !== curNode) {
                mostRight = mostRight.right
            }
            if (mostRight.right === null) {
                mostRight.right = curNode
                curNode = curNode.left
                continue
            }
            if (mostRight.right === curNode) {
                mostRight.right = null
                printNode(curNode.left)
            }
        }
        console.log(curNode)
        curNode = curNode.right
    }
}
// 处理完再反转回去
function printNode(node) {
    const reverseNode = reverseTree(node)
    let curNode = reverseNode
    while (curNode) {
        console.log(curNode)
        curNode = curNode.right
    }
    reverseTree (reverseNode)
}
// 类似反转链表
function reverseTree(node) {
    let pre = null
    let temp = null
    while(node){
        temp = node.right
        node.right = pre
        pre = node
        node = temp
    }
    return pre
}