具有巨大深度的植树--DFS遍历算法性能

时间:2016-12-16 08:47:28

标签: c algorithm data-structures tree traversal

今天,我为root树学习了3次DFS(深度优先搜索)遍历,即: 有序,预订&下订单遍历。

例如,如果我考虑预订遍历,

typedef struct SiblingTreeNode {
    struct SiblingTreeNode *parent;
    void *item;
    struct SiblingTreeNode *firstChild;
    struct SiblingTreeNode *nextSibling;
} Node;

typedef struct LCRSTree {
    Node *root;
    int size;
} Tree;


void preOrderTraverse(Node * node) {
    visit(node);

    if (node->firstChild) {
        printf("\n|");
        preOrderTraverse(node->firstChild);
    }

    if (node->nextSibling) {
        printf("-->");
        preOrderTraverse(node->nextSibling);
    }
}

void preOrder(Tree *tree) {
    preOrderTraverse(tree->root);
}

然后按以下顺序访问节点,

enter image description here

实际上在为NMS(网络管理系统)应用程序工作时,我们使用有根树(LCRS表示)来维护网络元素(度量)的层次结构,叶子节点的深度非常大。

渐近地,预先遍序遍历的空间复杂度为O(d),其中d是最低叶子的深度。

在应用这3次遍历中的任何一次时,由于堆栈溢出,应用程序很可能崩溃。

例如 - 如果考虑访问节点序列(上图),当您访问第3个节点时,调用堆栈将从根维护到叶子。

使用上面给定的Tree表示,不保持显式数据结构(如堆栈),如何在有根树上优化遍历算法?

注意:在构建时,Tree看起来像this

1 个答案:

答案 0 :(得分:2)

Pre-order遍历有一个非递归解决方案,它使用递归的调用堆栈的堆栈数据结构。 如果内存仍然存在问题,您可以设计一个堆栈以将其中的一部分卸载到存储中,并在需要时重新加载。

void iterativePreorder() {
    TreeNode top;
    if (root == null)
        return;

    Stack<SiblingTreeNode> st = new Stack<SiblingTreeNode>();
    st.push(root);

    while (!st.empty()) {
        top = st.pop();
        //do traversal effect
        if (top.right != null)
            st.push(top.right);
        if (top.left != null)
            st.push(top.left);
    }
}