【问题标题】:implement a Queue using a BST使用 BST 实现队列
【发布时间】:2012-11-18 21:01:01
【问题描述】:

如何使用 BST 实现队列。

这是这样做的方法吗,继续在树中插入节点,同时保持与每个节点关联的计数值,但是在删除时 BST 应该像队列(FIFO)一样工作,所以开始从 BST 中删除节点在树中具有最低的计数值。

我的问题和解决方案是否正确?如果不是,请解释一下这个问题。

【问题讨论】:

  • 将二叉树用于队列并不完全不寻常,但是二叉搜索树(节点按键排序的树)会有点奇怪——键只会重复排序树中已经存在的信息。
  • 你想做什么需要基于 BST 的队列?这就像用大炮击中射箭目标,我们应该说 overkill
  • 我没有做任何具体的事情,我很想知道它

标签: c++ c binary-search-tree


【解决方案1】:

BST 实际上是一种不适合用于支持队列的数据结构。你真的应该改用链表,因为它会更快、更简单、更简单。

但是,如果您坚持使用 BST...

您可以将 BST 用作优先级队列,并定义一个包含“队列索引”的包装器类型,这是对项目进行排序的依据。但是,您必须定义比较以考虑当前队列索引,否则您只能添加与索引类型的最高值和最低值之间的差值一样多的项目。

【讨论】:

  • 优先队列是使用最大/最小堆实现的,那么如何将堆用作 BST,反之亦然
  • @SumitKumarSaha 真的,我不知道。我认为 c++ 优先队列的实现方式与 java 的 PriorityQueue 相同,使用的是红黑树。显然我弄错了。谢谢你的澄清。
  • 实际上,是 Java 的 SortedSet 或类似的使用红黑树。 PriorityQueue 使用堆。
  • @OfirAttia 不,你真的不能。对优先级队列使用堆,对任何其他类型的队列使用环形缓冲区或链接节点。
  • @OfirAttia 没有。队列只有几个操作:添加一个项目(add),删除第一个项目(pop),检查第一个项目(top)。对于这些操作,与堆、节点列表或环形缓冲区相比,BST 将具有可恶的性能,并且绝对不能接受。如果需要快速成员资格测试 (find) 或快速插入 (insert),则使用 BST,而队列不需要。
【解决方案2】:

你可以有一个这样的队列:

BST // to store data
pointer to head; // Points to the head of the Queue
pointer to tail  // Points to the tail of the Queue

您还向 BST 的节点结构添加了一个指向另一个节点的指针,该节点将表示插入顺序。

struct Node{
  int x;
  //left pointer
  //right pointer
  struct Node *next_queune_element;
}

插入期间 当你想添加一个元素时,你首先访问指针tail指向的节点,让它指向你刚刚插入的新元素(BST节点)。然后更新尾指针以指向新元素。

删除期间 删除元素时,首先访问头指针指向的节点,将next_queune_element 存储在辅助临时变量中并删除节点。最后让head指针指向辅助临时变量。

【讨论】:

  • 它很有效,虽然它实际上不是 BST,但对于这个应用程序来说它确实比 BST 更好。
【解决方案3】:

我认为二叉树将是这里所需的数据结构,而不是二叉搜索树。在进行函数式编程时,使用二叉树实现队列可能很有用。您可以使用在每次推送和弹出操作后保持高度平衡的二叉树来做到这一点,因此它们将始终为 O(log n)。 Push 和 pop 的样子:

  • 在树的最左侧插入元素的函数(推送函数);
  • 从树的最右侧删除元素的函数(pop 函数)。

在这两种情况下,重新平衡都不会违反插入顺序。两者也很容易实现。您实际上正在使用具有更改的插入功能的 AVL 树。一个好处是元素不需要(完全)可订购。

【讨论】:

    猜你喜欢
    • 2019-06-21
    • 2015-10-03
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 2014-09-03
    相关资源
    最近更新 更多