通过修改morris遍历实现PreOrder和PostOrder遍历

发布于 2024-12-29 17:05:32 字数 101 浏览 1 评论 0原文

morris 遍历非常适合 O(n) 时间和 O(1) 空间的 InOrder 遍历。是否有可能仅通过改变一些东西就可以使用相同的算法实现 PreOrder 和 PostOrder 遍历。

The morris traversal works great for InOrder traversal with O(n) time and O(1) space. Is it possible to just by changing a few things achieve PreOrder and PostOrder traversal using the same algorithm.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

套路撩心 2025-01-05 17:05:32

我认为我们不能使用线程实现后序。
按照后序,我们必须遍历两个孩子,然后遍历他们的父母。
我们可以建立从子节点到父节点的链接,但之后我们无法向上移动这个父节点,因为它们没有链接。(一个指向左子节点,一个指向其右子节点,没有一个向上指向)

             1
            / \
           2   3
          / \
         4   5

我们可以在 4 的右节点创建一个线程指向节点 5 。
我们可以在 5 的右侧节点创建一个指向节点 2 的线程。

但在节点 2 处,没有空指针来创建任何线程。节点 2 已经有指向节点 4 和节点 4 的指针。 5.

I dont think we can Implement post order using threads .
In post order we have to traverse both the children then their parent.
We can establish a link from child to parent, but after that we cant go up this parent coz their are no links.(one points to left child and one to its right child none pointing upwards)

             1
            / \
           2   3
          / \
         4   5

we can create a thread at 4's right node pointing to node 5 .
We can create a thread at 5's right node pointing to node 2 .

But at node 2 there are no empty pointers to create any threads. Node 2 already has its pointers pointing to node 4 & 5.

红焚 2025-01-05 17:05:32

我知道使用 morison Algo 进行预购的解决方案。

这是java代码

public static void morisonPreOrder(TreeNode root) {
    TreeNode curr = root, tmp=null;

    while (curr != null) {
        if(curr.leftNode == null) {
            System.out.print(curr.value + "  ");
            curr = curr.rightNode;
        } else {
            tmp = curr.leftNode;
            while (tmp.rightNode != null && tmp.rightNode != curr) {
                tmp = tmp.rightNode;
            }

            if(tmp.rightNode == null) {
                System.out.print(curr.value + "  ");
                tmp.rightNode = curr;
                curr = curr.leftNode;
            } else {
                tmp.rightNode = null;
                curr = curr.rightNode;
            }
        }
    }
}

I know the solution for Preorder using morison Algo.

here is the java Code

public static void morisonPreOrder(TreeNode root) {
    TreeNode curr = root, tmp=null;

    while (curr != null) {
        if(curr.leftNode == null) {
            System.out.print(curr.value + "  ");
            curr = curr.rightNode;
        } else {
            tmp = curr.leftNode;
            while (tmp.rightNode != null && tmp.rightNode != curr) {
                tmp = tmp.rightNode;
            }

            if(tmp.rightNode == null) {
                System.out.print(curr.value + "  ");
                tmp.rightNode = curr;
                curr = curr.leftNode;
            } else {
                tmp.rightNode = null;
                curr = curr.rightNode;
            }
        }
    }
}
墨离汐 2025-01-05 17:05:32

后序可以通过简单地反转中序Morris算法来实现。解释一下,

按顺序 python Morris 实现:

def in_order(root):
    if not root:
        return []
    current = root
    in_order_list = []
    while current:
        if not current.left:
            in_order_list += [current.val] # Mark current as visited
            current = current.right
        else:
            # find the right most of the left tree
            predecessor = current.left
            while (predecessor.right) and (predecessor.right != current):
                predecessor = predecessor.right
            # and create a link from this to current
            if not predecessor.right:
                predecessor.right = current
                current = current.left
            else: # now bring back the tree to it's original shape
                 predecessor.right = None
                 in_order_list += [current.val]
                 current = current.right
    return in_order

对于后序,从 current 开始,如果 current.right 为空 - 开始向左看。如果不是,则找到最左边的前驱并将该前驱的左侧链接回当前。
(简而言之,按顺序从左向右翻转,并继续将节点插入到访问列表的开头;))

后序 Python Morris

def post_order(root):
    if not root:
        return []
    current = root
    post_order_list = []
    while current:
        if not current.right:
            post_order_list.insert(0, current.val)
            current = current.left
        else:
            # find left most of the right sub-tree
            predecessor = current.right
            while (predecessor.left) and (predecessor.left != current):
                predecessor = predecessor.left
            # and create a link from this to current
            if not predecessor.left:
                post_order_list.insert(0, current.val)
                predecessor.left = current
                current = current.right
            else:
                predecessor.left = None
                current = current.left
    return post_order

Post-order can be achieved by simply reversing the in-order Morris algorithm. To explain,

In-order python Morris implementation:

def in_order(root):
    if not root:
        return []
    current = root
    in_order_list = []
    while current:
        if not current.left:
            in_order_list += [current.val] # Mark current as visited
            current = current.right
        else:
            # find the right most of the left tree
            predecessor = current.left
            while (predecessor.right) and (predecessor.right != current):
                predecessor = predecessor.right
            # and create a link from this to current
            if not predecessor.right:
                predecessor.right = current
                current = current.left
            else: # now bring back the tree to it's original shape
                 predecessor.right = None
                 in_order_list += [current.val]
                 current = current.right
    return in_order

For post-order, begin with current and if current.right is empty - start looking towards left. If not, find left most predecessor and link the left of this predecessor back to current.
(In short, flip the lefts in in-order to rights and keep inserting nodes to the beginning of the visited list ;) )

Post-order Python Morris

def post_order(root):
    if not root:
        return []
    current = root
    post_order_list = []
    while current:
        if not current.right:
            post_order_list.insert(0, current.val)
            current = current.left
        else:
            # find left most of the right sub-tree
            predecessor = current.right
            while (predecessor.left) and (predecessor.left != current):
                predecessor = predecessor.left
            # and create a link from this to current
            if not predecessor.left:
                post_order_list.insert(0, current.val)
                predecessor.left = current
                current = current.right
            else:
                predecessor.left = None
                current = current.left
    return post_order
风苍溪 2025-01-05 17:05:32

以下是使用修改后的莫里斯遍历进行前序遍历的示例代码。

可以用类似的方式修改右前驱的左链接进行后序遍历。

我没有时间测试代码。如果这段代码有问题,请告诉我。

void preOrderNonRecursive( BSTNode* root )
{
    if(!root)
        return;
    BSTNode* cur = root;

    while(cur)
    {
        bool b = false;
        BSTNode* pre = NULL;
        if (cur->left)
        {
            pre = cur->left;
            while(pre->right && pre->right != cur)
                pre = pre->right;
            if(!pre->right)
            {
                pre->right = cur;
                b = true;
            }               
            else
                pre->right = NULL;
        }   
        else
            printf("%d\n",cur->val);

        if(b)
        {   
            printf("%d\n",cur->val);
            cur = cur->left;        
        }
        else            
            cur = cur->right;
    }
}

Here is the sample code for pre order traversal using modified morris traversal.

You can use in a similar way to modify the right predecessor's left link for post order traversal.

I didn't get time to test the code. Please let me know if something is wrong in this code.

void preOrderNonRecursive( BSTNode* root )
{
    if(!root)
        return;
    BSTNode* cur = root;

    while(cur)
    {
        bool b = false;
        BSTNode* pre = NULL;
        if (cur->left)
        {
            pre = cur->left;
            while(pre->right && pre->right != cur)
                pre = pre->right;
            if(!pre->right)
            {
                pre->right = cur;
                b = true;
            }               
            else
                pre->right = NULL;
        }   
        else
            printf("%d\n",cur->val);

        if(b)
        {   
            printf("%d\n",cur->val);
            cur = cur->left;        
        }
        else            
            cur = cur->right;
    }
}
孤独患者 2025-01-05 17:05:32

/没有堆栈和递归的 PreOrder 实现/

private static void morrisPreorder(){
        while(node != null){
            System.out.println(node.getData());
            if (node.getLeftNode() == null){
                node = node.getRightNode();
            } else {
                Node rightnode = node.getRightNode();
                Node current = node.getLeftNode();
                while(current.getRightNode() != null && current.getRightNode().getData() != node.getData())
                    current = current.getRightNode();
                if(current.getRightNode() == null){
                    current.setRightNode(node.getRightNode());
                    node = node.getLeftNode();
                } else {
                    node = node.getRightNode();
                }
            }
        }
    }

/PreOrder Implementation Without stack and recursion/

private static void morrisPreorder(){
        while(node != null){
            System.out.println(node.getData());
            if (node.getLeftNode() == null){
                node = node.getRightNode();
            } else {
                Node rightnode = node.getRightNode();
                Node current = node.getLeftNode();
                while(current.getRightNode() != null && current.getRightNode().getData() != node.getData())
                    current = current.getRightNode();
                if(current.getRightNode() == null){
                    current.setRightNode(node.getRightNode());
                    node = node.getLeftNode();
                } else {
                    node = node.getRightNode();
                }
            }
        }
    }
小霸王臭丫头 2025-01-05 17:05:32

前序遍历上面已经回答了。

对于后序遍历,答案也是“是”。

您需要的唯一修改是:
1、当前驱的右子节点为当前节点时,将右子节点置为空,反向输出当前节点左子节点到前驱的所有节点
2. 设置一个虚拟节点,并将其左子节点设置为树的根。

Java代码编写如下:

    private void printPostTraverse(List<Integer> traverseList, TreeNode start, TreeNode end) {
        TreeNode node = start;
        int insertIndex = traverseList.size();
        while (node != end) {
            traverseList.add(insertIndex, node.val);
            node = node.right;
        }
        traverseList.add(insertIndex, node.val);
    }

    public List<Integer> postorderMorrisTraversal(TreeNode root) {
        List<Integer> traverseList = new ArrayList<>();
        TreeNode dummy = new TreeNode(-1);
        dummy.left = root;
        TreeNode cur = dummy, prev = null;
        while (cur != null) {
            if (cur.left == null) {
                cur = cur.right;
            } else {
                prev = cur.left;
                while (prev.right != null && prev.right != cur)
                    prev = prev.right;

                if (prev.right == null) {
                    prev.right = cur;
                    cur = cur.left;
                } else {
                    // Modification on get the traversal list
                    printPostTraverse(traverseList, cur.left, prev);
                    prev.right = null;
                    cur = cur.right;
                }
            }
        }
        return traverseList;
    }

The preorder traversal has been answered above.

For the postorder traversal, the answer is "Yes" as well.

The only modifications you need are:
1. When the right child of the predecessor is current node, set the right child to null and reversely output all the nodes from the left child of the current node to the predecessor.
2. Set up a dummy node and set its left child to the root of the tree.

The Java code is written here:

    private void printPostTraverse(List<Integer> traverseList, TreeNode start, TreeNode end) {
        TreeNode node = start;
        int insertIndex = traverseList.size();
        while (node != end) {
            traverseList.add(insertIndex, node.val);
            node = node.right;
        }
        traverseList.add(insertIndex, node.val);
    }

    public List<Integer> postorderMorrisTraversal(TreeNode root) {
        List<Integer> traverseList = new ArrayList<>();
        TreeNode dummy = new TreeNode(-1);
        dummy.left = root;
        TreeNode cur = dummy, prev = null;
        while (cur != null) {
            if (cur.left == null) {
                cur = cur.right;
            } else {
                prev = cur.left;
                while (prev.right != null && prev.right != cur)
                    prev = prev.right;

                if (prev.right == null) {
                    prev.right = cur;
                    cur = cur.left;
                } else {
                    // Modification on get the traversal list
                    printPostTraverse(traverseList, cur.left, prev);
                    prev.right = null;
                    cur = cur.right;
                }
            }
        }
        return traverseList;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文