今天,我为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);
}
然后按以下顺序访问节点,
实际上在为NMS(网络管理系统)应用程序工作时,我们使用有根树(LCRS
表示)来维护网络元素(度量)的层次结构,叶子节点的深度非常大。
渐近地,预先遍序遍历的空间复杂度为O(d)
,其中d是最低叶子的深度。
在应用这3次遍历中的任何一次时,由于堆栈溢出,应用程序很可能崩溃。
例如 - 如果考虑访问节点序列(上图),当您访问第3个节点时,调用堆栈将从根维护到叶子。
使用上面给定的Tree
表示,不保持显式数据结构(如堆栈),如何在有根树上优化遍历算法?
注意:在构建时,Tree
看起来像this
答案 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);
}
}