【问题标题】:Early exit from a Morris inorder traversal提前退出 Morris 中序遍历
【发布时间】:2022-11-13 07:38:02
【问题描述】:

我正在使用 Morris 中序遍历来遍历(遍历所有节点)二叉树。相关代码(灵感来自the C code here)如下所示:

#include <stdio.h>  /* printf(). */
#include <stdlib.h>  /* NULL. */
struct node {
    struct node *left, *right;
    int data;
};
void traverse(struct node *root) {
    struct node *current = root;
    struct node *pre;
    while (current != NULL) { 
        if (current->left == NULL) goto process_node;
        /* Find the inorder predecessor of current */
        pre = current->left;
        while (pre->right != NULL && pre->right != current) {
            pre = pre->right;
        }
        if (pre->right == NULL) {
            /* Make current the right child of its inorder predecessor */
            pre->right = current;  /* This breaks the tree temporarily. */
            current = current->left;
        } else {
            /* Revert the changes made in the 'if' part to restore the
             * original tree i.e., fix the right child of predecessor.
             */
            pre->right = NULL;
          process_node:
            printf("%d ", current->data);
            if (current->data < 0) {
                /* !!! Add cleanup code here. */
                return;  /* Stop the traversal. */
            }
            current = current->right;
        }
    }
}

如果没有节点具有负值,则此代码可以正确编译和工作。对于具有负值的节点,我想在第一个负值之后立即停止遍历。但是,此时某些 -&gt;right 指针已损坏(请参阅代码行这打破了在其中),我需要添加清理代码(到代码行!!!在其中)恢复这些损坏的指针,并使树再次有效。

我的问题:这个清理代码应该是什么?

请注意,我仍然希望保留 Morris 中序遍历算法,因为该程序运行在一个资源受限的系统中,该系统具有一个小的固定堆栈并且没有可用的动态内存。因此,用另一个不需要清理的遍历算法替换 Morris 算法,但它使用更多内存(例如递归遍历或手动管理路径堆栈的遍历)不是我问题的有效答案。

【问题讨论】:

    标签: c binary-tree tree-traversal


    【解决方案1】:

    可能有更好的解决方案,但这是我一起破解的。它通过拥有一个新的exit 变量来工作,该变量在读取负值时被标记。然后它继续像往常一样运行,直到运行函数的现有代码以恢复更改,此时它将提前退出。

    此实现的一个缺陷是,如果负值节点不是叶节点,程序仍将尝试在此之前处理另一个节点。将 process_node 标签的大部分代码包装在 if (!exit) 中,这样当它试图退出时它就不会被处理可以解决这个问题。

    void traverse(struct node *root) {
        struct node *current = root;
        struct node *pre;
        int exit = 0;
        while (current != NULL) {
            if (current->left == NULL) goto process_node;
            /* Find the inorder predecessor of current */
            pre = current->left;
            while (pre->right != NULL && pre->right != current) {
                pre = pre->right;
            }
            if (pre->right == NULL) {
                /* Make current the right child of its inorder predecessor */
                pre->right = current;  /* This breaks the tree temporarily. */
                current = current->left;
            } else {
                /* Revert the changes made in the 'if' part to restore the
                 * original tree i.e., fix the right child of predecessor.
                 */
                pre->right = NULL;
                if (exit) return;
              process_node:
                if (!exit){
                    printf("%d ", current->data);
                    if (current->data < 0) {
                        /* !!! Add cleanup code here. */
                        exit = 1;
                    }
                }
                current = current->right;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 2021-11-27
      • 1970-01-01
      • 2019-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多