【问题标题】:Left Child Right Sibling tree - Depth First Search - Performance左子右兄弟树 - 深度优先搜索 - 性能
【发布时间】:2016-12-11 18:35:48
【问题描述】:

对于下面的树,

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

typedef struct Tree{
  SibTreeNode *root;
  int size; // number of nodes in tree
}Tree;

1)

假设一棵树的深度很大,为了避免堆栈溢出,我们可以不使用递归进行DFS吗?

2)

一般来说,一个树节点有n个子指针和数据指针(item),从对树的操作性能方面来说,维护兄弟节点(nextSibling)和第一个子节点(firstChild)有什么好处和父指针(parent)?

【问题讨论】:

标签: c performance data-structures tree


【解决方案1】:
  1. 是的。使用显式数据结构总是可能的 而是根据需要(例如您自己的显式堆栈)来跟踪 你在哪里或者你还需要做什么。这样做的一个原因可能是调用堆栈空间有限。一些语言以一种自动避免堆栈开销的方式支持称为“tail recursion”的简单递归案例。

    编辑:在这种特定情况下,您不需要跟踪超过当前节点,请参见下面添加的代码。

  2. “左孩子/左兄弟”结构的优点是您可以拥有任意数量的孩子,而无需额外的数据结构(例如列表或数组)来管理孩子。一个缺点是您不能直接访问第 n 个孩子 - 访问第 n 个孩子是一个 O(n) 操作。

给定数据结构的非递归 DFS:

void Dfs(Tree* tree) {
  SiblingTreeNode* current = tree.root;

  while (current != nullptr) {

    visit (current);

    if (current->firstChild != nullptr) {
      current = current->firstChild;
    } else if (current->nextSibling != nullptr) {
      current = current->nextSibling;
    } else {
      do {
        current = current->parent;
      } while (current != nullptr && current->nextSibling == nullptr);
      if (current != nullptr) {
         current = current->nextSibling;
      }
    }
  }  // while
}  // Dfs

【讨论】:

  • 显式或隐式,堆栈深度仍为O(logN)
  • @Groo 不一定——这取决于树的深度。
  • @templatetypedef:我的观点是(以大 O 表示法)空间复杂度不取决于您是否简单地重写算法以使用显式堆栈。所以,是的,如果我们不是在谈论平衡二叉树,它们都取决于树的深度。
  • @Groo 没有明确的数据结构(如堆栈)使用表示赞赏。内存少。我们不能依赖父指针进行 DFS 吗?
  • 我已经添加了一个实现。拥有父指针使您无需显式堆栈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多