看似工作的算法,用于在数组中存储二进制搜索树而不浪费空间

时间:2016-01-30 19:59:13

标签: c++ arrays algorithm serialization binary-search-tree

在尝试理解二进制(搜索)树时,我偶然发现了BST是否可以有效地存储在平面阵列中的问题(即,没有浪费空间)。谷歌搜索和在论坛(包括SO)搜索后,我没有找到任何让我满意的东西。大多数人希望存储BT(l=2*i+1r=2*i+2)或接受节点的空子节点表示为nil值(并且存储类似,不必要地占用空间)的事实。 / p>

所以我编写了自己的算法,利用了BST中的子节点具有特定排序属性(小于root:left,大于root:right)这一事实。

要存储BST,我只是将其线性地写入数组,深度优先。这发生在O(n)中,递归到树的子节点中。那么数组的长度恰好为n个条目,n是BST中的节点数。

要从数组重建BST,我在数组中遇到新条目时遵循两条规则:

  • 下一个左侧节点(如果存在)是下一个比当前节点小的节点。

  • 下一个正确的节点(如果存在)是下一个...

    • ......比当前的
    • 更大
    • ...在最后一次分支left
    • 时,不大于最小的父键
    • ...如果在父级的left分支
    • 中小于父级

这也发生在O(n)

对于非常非常大的随机结构树(只要它们是BST),它的效果非常好。经验测试从未表现出任何问题。我在C ++ here中创建了一个工作代码示例,两个转换函数是toArrayfromArray

现在问我的问题: 这概括了吗?我害怕用这个来监督关键问题。事实上,我还没有在网上发现任何其他内容,这让我想知道是否

a )我太傻了,无法找到它,

b )这是常识,没有人谈论它或

c )这是完全错误的。

我会非常感谢任何精通这个主题的人来启发我。

非常感谢。

修改

在谷歌更多地完全忽略阵列细节之后,我找到了几个有效的解决方案。最突出的一个(如herehere所述)是使用预订遍历来存储BST。

1 个答案:

答案 0 :(得分:1)

最终,我自己找到了解决方案。用于从BST深度优先创建的数组重建BST的技术基于预先遍序。

我找到了解决方案here,并在我自己的BST课程here中实现了该解决方案。重要的部分如下:

bool BinarySearchTree::fromArrayPreorderTraversal(std::vector<unsigned int> vecArray, unsigned int& unCurrentIndex, unsigned int unMin, unsigned int unMax) {
  bool bResult = false;

  if(unCurrentIndex < vecArray.size()) {
    unsigned int unVal = vecArray[unCurrentIndex];

    if(unVal > unMin && unVal < unMax) {
      bResult = true;
      this->setKey(unVal);
      unCurrentIndex++;

      if(unCurrentIndex < vecArray.size()) {
        if(!this->left(true)->fromArrayPreorderTraversal(vecArray, unCurrentIndex, unMin, unVal)) {
          this->setLeft(NULL);
        }

        if(!this->right(true)->fromArrayPreorderTraversal(vecArray, unCurrentIndex, unVal, unMax)) {
          this->setRight(NULL);
        }
      }
    }
  }

  return bResult;
}

这里是以下形式的BST:

      10
     /  \
    5    20
   / \     \
  2   7     30
 /
1

可用作预订遍历数组:

10 5 2 1 7 20 30

首先是父节点,然后是左子节点,然后是右子节点(递归地)。这是BST的深度优先表示。

该算法获取有效范围的键,以接受leftright侧的新节点作为参数(此处为unMinunMax)并基于那,决定是否应该创建节点。完整的BST包括其原始结构以这种方式重建。

此时间复杂度(根据上面的参考)是O(n)。由于没有浪费空间,空间复杂度也是O(n)

这个算法比我在问题中提出的算法更优雅。它似乎也是进行这种重建的一般方式。