如何在最小堆中实现 downHeap() 函数?

How can I implement downHeap() function in a min-heap?

我正在尝试为最小堆编写 downHeap() 函数,我将在其中检查根节点的子节点是否小于根节点,如果是,我将交换它们的值。 class 节点已经为我定义,并且有一个 'left' 和 'right' 子指针以及 'value'。以下是我目前的代码:

void downHeap(Node *n) {

    if (!n) {return;}

    if (!n->left && !n->right) {return;}

    if (n->left && n->right){
        if (n->left->value < n->right->value){
          if (n->left->value < n->value){
            std::swap(n->value, n->left->value);
            downHeap(n->left);
          }
      else if (n->right->value < n->left->value){
          if (n->right->value < n->value){
            std::swap(n->value, n->right->value);
            downHeap(n->right);
          }
        }
      }
    }

这是我主要测试的功能:

int main() {
  Node *n = new Node(7);
  n->left = new Node(6);
  n->right = new Node(9);
  n->left->left = new Node(4);
  n->left->right = new Node(5);
  downHeap(n);
  printTreeVertical(n);

  delete n;
  n = nullptr;
  return 0;
}

我生成的树:

##6 (X) Greater than child value 4
#|
#|_ 4.  // 4 is left child and 9 is right child of 6 in this tree.
#|..|
#|..|_ 7 //7 and 5 are children of 4.
#|..|..|
#|..|..|_ [null]
#|..|..|
#|..|..|_ [null]
#|..|
#|..|_ 5
#|.....|
#|.....|_ [null]
#|.....|
#|.....|_ [null]
#|
#|_ 9
#...|
#...|_ [null]
#...|
#...|_ [null]

如您所见,6 是根节点,而 4 应该是。然后 4 和 5 应该再次交换位置。我现在的功能似乎只交换 rootNode 一次并继续下降但不会从一开始就重新检查。我试图在 if 条件的末尾再次添加 downHeap(n) 但如果我这样做,没有任何输出。请帮忙!

你首先需要深入了解,然后检查交换条件。 我会做这样的事情:

void mySwap(Node* a, Node* b)
{
    int tmp = a->val;
    a->val = b->val;
    b->val = tmp;
}

void downHeap(Node* root)
{
    node_t* tmp = NULL;

    if(root == NULL) return;

    downHeap(root->left);
    downHeap(root->right);

    if(root->left == NULL && root->right == NULL) return;

    if(root->left != NULL && root->right != NULL)
    {
        if(root->left->val < root->right->val)
            tmp = root->left;
        else 
            tmp = root->right;
    }
    else
    {
        if(root->left != NULL)
            tmp = root->left;
        if(root->right != NULL)
            tmp = root->right;
    }

    if(tmp->val < root->val)
        mySwap(root, tmp);
}

完成左右子树后,检查当前节点的 children.

如果当前节点是叶节点(即没有children)则无事可做

如果当前节点有两个children则取两者之间的最小值

如果当前节点只有一个 child,那就是你要检查的 tmp

最后检查交换条件。

不确定这是否是自上而下的方法,但这种情况下的时间复杂度会比另一种好。