【问题标题】:Find median in binary search tree在二叉搜索树中查找中位数
【发布时间】:2023-04-02 15:11:01
【问题描述】:

编写函数T ComputeMedian() const 的实现,该函数在 O(n) 时间内计算树中的中值。假设这棵树是一个 BST,但不一定是平衡的。回想一下,n 个数字的中位数定义如下:如果 n 为奇数,则中位数为 x,使得小于 x 的值的数量等于大于 x 的值的数量。如果 n 是偶数,则一加小于 x 的值的数量等于大于 x 的值的数量。例如,给定数字 8、7、2、5、9,中位数为 7,因为有两个小于 7 的值和两个大于 7 的值。如果我们将数字 3 添加到集合中,则中位数变为 5。

这里是二叉搜索树节点的类:

template <class T>
class BSTNode
{
public:
BSTNode(T& val, BSTNode* left, BSTNode* right);
~BSTNode();
T GetVal();
BSTNode* GetLeft();
BSTNode* GetRight();

private:
T val;
BSTNode* left;
BSTNode* right;  
BSTNode* parent; //ONLY INSERT IS READY TO UPDATE THIS MEMBER DATA
int depth, height;
friend class BST<T>;
};

二叉搜索树类:

template <class T>
class BST
{
public:
BST();
~BST();

bool Search(T& val);
bool Search(T& val, BSTNode<T>* node);
void Insert(T& val);
bool DeleteNode(T& val);

void BFT(void);
void PreorderDFT(void);
void PreorderDFT(BSTNode<T>* node);
void PostorderDFT(BSTNode<T>* node);
void InorderDFT(BSTNode<T>* node);
void ComputeNodeDepths(void);
void ComputeNodeHeights(void);
bool IsEmpty(void);
void Visit(BSTNode<T>* node);
void Clear(void);

private:
BSTNode<T> *root;
int depth;
int count;
BSTNode<T> *med; // I've added this member data.

void DelSingle(BSTNode<T>*& ptr);
void DelDoubleByCopying(BSTNode<T>* node);
void ComputeDepth(BSTNode<T>* node, BSTNode<T>* parent);
void ComputeHeight(BSTNode<T>* node);
void Clear(BSTNode<T>* node);

};

我知道我应该先计算树的节点,然后进行中序遍历,直到我到达第 (n/2) 个节点并返回它。我只是不知道怎么做。

【问题讨论】:

  • 在列表的情况下,您必须在两端开始指针并向内工作以找到中位数。但是由于您的树不平衡,因此最坏的情况会简化为链表。因此,你不能避免做同样的事情。从最小值和最大值开始指针,并交替计算 inorder-successor(min) 和 inorder-predecessor(max) 直到它们相等。
  • @BadZen 我对“inorder-predecessor”不太熟悉..您能否进一步解释一下?
  • Next() 和 Prev() 树值。

标签: algorithm tree binary-search-tree median


【解决方案1】:

正如你提到的,首先找到节点的数量是相当容易的,进行任何遍历:

findNumNodes(node):
   if node == null:
       return 0
   return findNumNodes(node.left) + findNumNodes(node.right) + 1

然后,当节点编号为 n/2 时,中序遍历中止:

// index is a global variable / class variable, or any other variable that is constant between all calls
index=0
findMedian(node):
   if node == null:
       return null
   cand = findMedian(node.left)
   if cand != null:
        return cand
   if index == n/2:
       return node
   index = index + 1
   return findMedian(node.right)

这个想法是按顺序遍历以排序方式处理 BST 中的节点。因此,由于树是 BST,您处理的 ith 节点按顺序是 ith 节点,i==n/2 当然也是如此,当您找到它时,它是 n/2th节点,你返回它。


附带说明一下,您可以向 BST 添加功能以高效查找 ith 元素(O(h),其中 h 是树的高度),使用 order statistics trees

【讨论】:

  • 谢谢你的回复,不过我已经想到了。我的问题是我的函数应该看起来像这样 T ComputeMedian() const 所以你可以看到,它没有参数(我现在将编辑我的帖子)是否可以这样做 template &lt;class T&gt; T BST&lt;T&gt;::ComputeMedian() const { ComputeMedian(root); } 我实现 ComputeMedian(BSTNode&lt;T&gt;* node) 就像你说?这仍然是 O(n) 吗?
  • @NataliAyoub 是的,你只是用不断的操作来结束它。
  • 我刚刚编辑了我的帖子并添加了代码以及错误,请您检查一下并告诉我有什么问题吗?
  • @NataliAyoub 这超出了原始问题的范围,您应该回滚到以前的版本,并提出一个新问题 - 链接到这个问题并说明您从那以后做了什么,什么是你遇到的新问题。
  • @NataliAyoub 新问题就像听起来一样 - 一个新问题。我删除了编辑并将问题恢复到原始状态。您应该在新问题中提出新问题,以及如何处理您遇到的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-11
  • 2011-02-05
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多