二叉树到堆树的转换 - 陷入无限循环
Binary Tree to Heap Tree Conversion - Stuck in infinite loop
在解决问题时,我尝试了以下解决方案。不知何故,我的输出陷入了无限循环,没有打印结果或更新的堆树。
给定一棵树,其左右子树都是最小堆,但根节点不维护最小堆属性。您的代码应修改以 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->left, n->right));
在这里,当您真正想要比较您所引用的两个对象中的值时,您正在比较两个指针,而 return 是指向具有较小值的对象的指针。即:
mino = (n->left->value < n->right->value) ? n->left : n->right;
同样在这行代码中:
} else if (n->left->value > n->value & n->right->value > n->value){
您可能需要 &&
(逻辑与)而不是 &
(按位与)。参见 https://www.geeksforgeeks.org/what-are-the-differences-between-bitwise-and-logical-and-operators-in-cc/。
最后,您的代码格式有点不对,所以很难分辨,但看起来 return
语句在 downHeap
函数的 while
循环之外。如果它在循环体之外,则可能导致无限循环。
这是我想到的最简单的解决方案。
尝试此代码以获得完整的解决方案。
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;
}
如果您定义一个辅助函数来交换节点值,您可以使您的代码更简洁,并且可以很容易地实现递归。例如:
// 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;
}
}
}
在解决问题时,我尝试了以下解决方案。不知何故,我的输出陷入了无限循环,没有打印结果或更新的堆树。
给定一棵树,其左右子树都是最小堆,但根节点不维护最小堆属性。您的代码应修改以 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->left, n->right));
在这里,当您真正想要比较您所引用的两个对象中的值时,您正在比较两个指针,而 return 是指向具有较小值的对象的指针。即:
mino = (n->left->value < n->right->value) ? n->left : n->right;
同样在这行代码中:
} else if (n->left->value > n->value & n->right->value > n->value){
您可能需要 &&
(逻辑与)而不是 &
(按位与)。参见 https://www.geeksforgeeks.org/what-are-the-differences-between-bitwise-and-logical-and-operators-in-cc/。
最后,您的代码格式有点不对,所以很难分辨,但看起来 return
语句在 downHeap
函数的 while
循环之外。如果它在循环体之外,则可能导致无限循环。
这是我想到的最简单的解决方案。
尝试此代码以获得完整的解决方案。
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;
}
如果您定义一个辅助函数来交换节点值,您可以使您的代码更简洁,并且可以很容易地实现递归。例如:
// 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;
}
}
}