【问题标题】:Binary Tree to Heap Tree Conversion - Stuck in infinite loop二叉树到堆树的转换 - 陷入无限循环
【发布时间】:2020-08-27 20:02:28
【问题描述】:

在解决问题时,我尝试了以下解决方案。不知何故,我的输出陷入了无限循环,没有打印结果或更新的堆树。

给定一棵树,其中左右子树都是最小堆,但根节点不保持最小堆属性。您的代码应修改以 Node* n 为根的树,使其成为最小堆。 (这意味着您需要满足最小堆属性: 一个节点的值可以等于它的一个或两个子节点是可以的,但该节点的值不能大于它的任何一个子节点。您不必尝试平衡树或使其成为完整的树。)

#include <iostream>
#include <string>

You have the following class Node already defined.
You cannot change this class definition, so it is
shown here in a comment for your reference only:

class Node {
public:
  int value;
  Node *left, *right;
  Node(int val = 0) { value = val; left = right = nullptr; }
  ~Node() {
    delete left;
    left = nullptr;
    delete right;
    right = nullptr;
  }
};

This function has also previously been defined for you:

void printTreeVertical(const Node* n);

You can use it to print a verbose, vertical diagram of
a tree rooted at n. In this vertical format, a left child
is shown above a right child in the same column. If no
child exists, [null] is displayed.

*/

void downHeap(Node *n) {
    Node *curr = new Node();
    Node *mino = new Node();

  if (n == nullptr ){
    return;
  } else if (n->left->value > n->value & n->right->value > n->value){
    return;
  // } else if (n->left== nullptr & n->right== nullptr) {
  //   return;

  //   } 
  } else {
    // node* curr = new Node(n)
    // n = new Node((std::min(n->left->value, n->right->value));
    // if (n->left->value)
    while(n->left!= nullptr & n->right!= nullptr){
      if (n->left == nullptr){
        mino = n->right;
      } else if (n->right == nullptr) {
        mino = n->left;
      } else {
        mino = (std::min(n->left, n->right));
      }

      std::cout << n->value << std::endl;
      std::cout << mino->value << std::endl;




        if(n->value > mino-> value){
            curr->value = n->value;
            n->value = mino->value;
            mino->value = curr->value;
            std::cout << n->value << std::endl;
            std::cout << mino->value << std::endl;
            downHeap(mino);
          }
        }
        return;
      }
  }

  // Implement downHeap() here.



// You can also use this compact printing function for debugging.
void printTree(Node *n) {
  if (!n) return;
  std::cout << n->value << "(";
  printTree(n->left);
  std::cout << ")(";
  printTree(n->right);
  std::cout << ")";
}

int main() {
  Node *n = new Node(100);
  n->left = new Node(1);
  n->left->left = new Node(3);
  n->right = new Node(2);
  n->right->left = new Node(3);
  n->right->right = new Node(4);
  n->right->right->right = new Node(5);
  std::cout << std::endl << "BEFORE - Vertical printout:" << std::endl;
  printTreeVertical(n);

  downHeap(n);

  std::cout << "Compact printout:" << std::endl;
  printTree(n);
  std::cout << std::endl << " AFTER Vertical printout:" << std::endl;
  printTreeVertical(n);

  delete n;
  n = nullptr;

  return 0;
}

请建议我缺少什么。我觉得我把它弄得太复杂了。另外,我没有任何其他功能,例如将二叉树转换为堆最小值的交换。我也没有使用数组或向量。所以,如果你能给我提供简单的解决方案,我将不胜感激。

【问题讨论】:

  • 在调试器中加载您的程序,然后单步执行。这将准确地向您显示事情在哪里偏离了轨道。如果您不知道如何使用调试器,那么现在是学习的最佳时机。
  • mino = (std::min(n-&gt;left, n-&gt;right)); 可能是一个错误。我想你想要n-&gt;left-&gt;valuen-&gt;right-&gt;value。此外,在(n-&gt;left== nullptr &amp; n-&gt;right== nullptr) 中,您可能需要&amp;&amp;。同样的事情在上面几行。最后,编辑您的问题以修复缩进。我认为问题在于您在downHeap 中的returnwhile 正文之外,这可能会导致无限循环。
  • @JimMischel 我想返回 mino 作为 root 左右子节点中最小的节点。如果我使用 -> value,它将只返回整数和注释节点。请纠正我或让我知道更好的方法。
  • 我看到了问题。您真正想要的是具有最小值的节点。 std::min 无法做到这一点。您需要比较这些值并返回节点。 if (node-&gt;left-&gt;value &lt; node-&gt;right-&gt;value) return node-&gt;left; else return node-&gt;right;
  • @JimMischel 谢谢。确切地。这就是问题所在。它像魅力一样固定。

标签: c++ recursion data-structures binary-tree heap


【解决方案1】:

你的主要问题是这行代码:

    mino = (std::min(n->left, n->right));

在这里,当您真正想要比较您所引用的两个对象中的值时,您正在比较两个指针,并返回一个指向具有较小值的对象的指针。那就是:

mino = (n->left->value < n->right->value) ? n->left : n->right;

也在这行代码中:

} else if (n->left->value > n->value & n->right->value > n->value){

您可能想要&amp;&amp;(逻辑与)而不是&amp;(按位与)。见https://www.geeksforgeeks.org/what-are-the-differences-between-bitwise-and-logical-and-operators-in-cc/

最后,您的代码格式有点偏离,因此很难分辨,但看起来return 语句位于while 函数的while 循环之外。如果它在循环体之外,则可能导致无限循环。

【讨论】:

    【解决方案2】:

    这是我想出的最简单的解决方案。

    【讨论】:

      【解决方案3】:

      试试这个代码以获得完整的解决方案。

      void downHeap(Node *n) {
        // check if it is a leaf node
        if (n->left == NULL && n->right == NULL) {
          return;
        }
      
        if ((n->left != NULL) && (n->right != NULL)) {
          if ((n->value <= n->left->value) && (n->value <= n->right->value)) {
            return;
          } 
        }
      
        // Node passed in is not a leaf
        // If left is null, we can focus on the right first
        // If the right node has a greater value
        if (n->right != NULL) {
          if ((n->left == NULL) && (n->right->value < n->value)) {
            int rightnodevalue = n->right->value;
            int nodevalue = n->value;
      
            n->value = rightnodevalue;
            n->right->value = nodevalue;
      
            if (n->right != NULL) {
              downHeap(n->right);
              return;
            }  
          }
        }
      
      
        // Node passed in is not a leaf
        // Left is not null
        // First check if right is null
        // If right is null, we can focus on the left first
        // If the left node has a greater value
        if (n->left != NULL) {
          if ((n->right == NULL) && (n->left->value < n->value)) {
            int leftnodevalue = n->left->value;
            int nodevalue = n->value;
      
            n->value = leftnodevalue;
            n->left->value = nodevalue;
      
            if (n->left != NULL) {
              downHeap(n->left);
              return;
            }
          }
        }
      
      
        // Node passed in is not a leaf
        // Left is not null
        // Right is not null
        // If left is less than right
        if ((n->left != NULL) && (n->right != NULL)) {
          if (n->left->value < n->right->value) {
            int leftnodevalue = n->left->value;
            int nodevalue = n->value;
      
            n->value = leftnodevalue;
            n->left->value = nodevalue;
      
            if (n->left != NULL) {
              downHeap(n->left);
              return;
            }
          }
          else {
            // Proceed to swap the parent and the right node
            // Reference pointers for child's pointers
            int rightnodevalue = n->right->value;
            int nodevalue = n->value;
      
            n->value = rightnodevalue;
            n->right->value = nodevalue;
      
            if (n->right != NULL) {
              downHeap(n->right);
              return;
            }
          }
        }
      
        return;
      }
      

      【讨论】:

        【解决方案4】:

        如果你定义一个辅助函数来交换节点值,你可以让你的代码更简洁,并且很容易实现递归。例如:

        // DEFINE HELPER FUNCTION
        void compareSwap(Node *a, Node *b) {
            int temp;
            if (a->value > b->value) {
                temp = b->value;
                b->value = a->value;
                a->value = temp;
            }
            return;
        }
        
        void downHeap(Node *n) {
          Node *compNode;
        
        // 1. n is a leaf
            if (!n->left && !n->right) {
                return;
            }
        
        // 2. n has one left child
          else if (n->left && !n->right) {
            if (n->value > n->left->value) {
              compareSwap(n, n->left);
              downHeap(n->left);
            }
            return;
          }
        
        // 3. n has one right child
          else if (!n->left && n->right) {
            if (n->value > n->right->value) {
              compareSwap(n, n->right);
              downHeap(n->right);
            }
            return;
          }
        
        // 4. n has two children ... (n->left && n->right) 
            else {
            // HEAP IS SATISFIED, RETURN NOTHING
                if ((n->value <= n->left->value) && (n->value <= n->right->value)) {
                    return;
                }
            // RIGHT IS LESS THAN n BUT LEFT IS NOT, SWAP RIGHT
            else if (((n->value <= n->left->value) && (n->value > n->right->value))) {
              compareSwap(n, n->right);
              downHeap(n->right);
              return;
            }
            // LEFT IS LESS THAN n BUT RIGHT IS NOT, SWAP LEFT
            else if (((n->value > n->left->value) && (n->value <= n->right->value))) {
              compareSwap(n, n->left);
              downHeap(n->left);
              return;
            }
            // BOTH ARE LESS THAN, SWAP MIN
            else {
              compNode = (n->left->value < n->right->value) ? n->left : n->right; 
              compareSwap(n, compNode);
              downHeap(compNode);
              return;
            }
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2015-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-28
          • 1970-01-01
          • 2021-12-10
          相关资源
          最近更新 更多