C++ 代码中的指针和 AVL 树有问题
Having issues with pointers and AVL tree in C++ code
我刚开始在我的数据结构和算法中学习 AVL 树 class。我在 Geeks for Geeks 上找到了将一个新节点插入树中并对其进行平衡的代码。代码如下所示。
// C++ program to insert a node in AVL tree
#include <iostream>
using namespace std;
// An AVL tree node
class Node
{
public:
int key;
Node *left;
Node *right;
int height;
};
// A utility function to get maximum
// of two integers
int max(int a, int b);
// A utility function to get the
// height of the tree
int height(Node *N)
{
if (N == NULL)
return 0;
return N->height;
}
// A utility function to get maximum
// of two integers
int max(int a, int b)
{
return (a > b)? a : b;
}
/* Helper function that allocates a
new node with the given key and
NULL left and right pointers. */
Node* newNode(int key)
{
Node* node = new Node();
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially
// added at leaf
return(node);
}
// A utility function to right
// rotate subtree rooted with y
// See the diagram given above.
Node *rightRotate(Node *y)
{
Node *x = y->left;
Node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left),
height(y->right)) + 1;
x->height = max(height(x->left),
height(x->right)) + 1;
// Return new root
return x;
}
// A utility function to left
// rotate subtree rooted with x
// See the diagram given above.
Node *leftRotate(Node *x)
{
Node *y = x->right;
Node *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left),
height(x->right)) + 1;
y->height = max(height(y->left),
height(y->right)) + 1;
// Return new root
return y;
}
// Get Balance factor of node N
int getBalance(Node *N)
{
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
// Recursive function to insert a key
// in the subtree rooted with node and
// returns the new root of the subtree.
Node* insert(Node* node, int key)
{
/* 1. Perform the normal BST insertion */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
else // Equal keys are not allowed in BST
return node;
/* 2. Update height of this ancestor node */
node->height = 1 + max(height(node->left),
height(node->right));
/* 3. Get the balance factor of this ancestor
node to check whether this node became
unbalanced */
int balance = getBalance(node);
// If this node becomes unbalanced, then
// there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node->left->key)
{
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node->right->key)
{
node->right = rightRotate(node->right);
return leftRotate(node);
}
/* return the (unchanged) node pointer */
return node;
}
// A utility function to print preorder
// traversal of the tree.
// The function also prints height
// of every node
void preOrder(Node *root)
{
if(root != NULL)
{
cout << root->key << " ";
preOrder(root->left);
preOrder(root->right);
}
}
// Driver Code
int main()
{
Node *root = NULL;
/* Constructing tree given in
the above figure */
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
/* The constructed AVL Tree would be
30
/ \
20 40
/ \ \
10 25 50
*/
cout << "\n\n" << "Preorder traversal of the "
"constructed AVL tree is \n";
preOrder(root);
cout << "\n\n";
return 0;
}
// This code is contributed by
// rathbhupendra
我理解代码是如何工作的(至少我认为是这样)。我稍微编辑了代码以尝试稍微不同的方法。对于 leftRotate 和 rightRotate 函数,最初,它们将指针作为参数,return 旋转后的指针 ("Node *leftRotate(Node *x)")。我试图通过引用指针参数和 return 类型 void ("void leftRotate(Node*& x)") 传递来改变它。代码如下所示(我在我更改原始代码的所有地方旁边添加了注释“//CHANGED”)。
// C++ program to insert a node in AVL tree
#include <iostream>
using namespace std;
// An AVL tree node
class Node
{
public:
int key;
Node *left;
Node *right;
int height;
};
// A utility function to get maximum
// of two integers
int max(int a, int b);
// A utility function to get the
// height of the tree
int height(Node *N)
{
if (N == NULL)
return 0;
return N->height;
}
// A utility function to get maximum
// of two integers
int max(int a, int b)
{
return (a > b)? a : b;
}
/* Helper function that allocates a
new node with the given key and
NULL left and right pointers. */
Node* newNode(int key)
{
Node* node = new Node();
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially
// added at leaf
return(node);
}
// A utility function to right
// rotate subtree rooted with y
// See the diagram given above.
void rightRotate(Node*& y) //CHANGED
{
Node *x = y->left;
Node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left),
height(y->right)) + 1;
x->height = max(height(x->left),
height(x->right)) + 1;
// Return new root
//return x; //CHANGED
}
// A utility function to left
// rotate subtree rooted with x
// See the diagram given above.
void leftRotate(Node*& x) //CHANGED
{
Node *y = x->right;
Node *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left),
height(x->right)) + 1;
y->height = max(height(y->left),
height(y->right)) + 1;
// Return new root
//return y; //CHANGED
}
// Get Balance factor of node N
int getBalance(Node *N)
{
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
// Recursive function to insert a key
// in the subtree rooted with node and
// returns the new root of the subtree.
Node* insert(Node* node, int key)
{
/* 1. Perform the normal BST insertion */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
else // Equal keys are not allowed in BST
return node;
/* 2. Update height of this ancestor node */
node->height = 1 + max(height(node->left),
height(node->right));
/* 3. Get the balance factor of this ancestor
node to check whether this node became
unbalanced */
int balance = getBalance(node);
// If this node becomes unbalanced, then
// there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
rightRotate(node); //CHANGED
// Right Right Case
if (balance < -1 && key > node->right->key)
leftRotate(node); //CHANGED
// Left Right Case
if (balance > 1 && key > node->left->key)
{
leftRotate(node->left); //CHANGED
rightRotate(node); //CHANGED
}
// Right Left Case
if (balance < -1 && key < node->right->key)
{
rightRotate(node->right); //CHANGED
leftRotate(node); //CHANGED
}
/* return the (unchanged) node pointer */
return node;
}
// A utility function to print preorder
// traversal of the tree.
// The function also prints height
// of every node
void preOrder(Node *root)
{
if(root != NULL)
{
cout << root->key << " ";
preOrder(root->left);
preOrder(root->right);
}
}
// Driver Code
int main()
{
Node *root = NULL;
/* Constructing tree given in
the above figure */
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
/* The constructed AVL Tree would be
30
/ \
20 40
/ \ \
10 25 50
*/
cout << "\n\n" << "Preorder traversal of the "
"constructed AVL tree is \n";
preOrder(root);
cout << "\n\n";
return 0;
}
// This code is contributed by
// rathbhupendra
我这样做的逻辑是,我可以通过引用传递指针,而不是 return 旋转指针,允许函数对指针本身进行旋转,而不是对指针的副本进行旋转指针。但是,当我 运行 这段代码时,我得到分段错误或只是没有输出(在 GeeksforGeeks 编码环境中它的分段错误和在 VS 代码上它只是没有输出)。有没有我也应该改变的东西,或者我只是做错了。我之前在以前的代码中通过引用传递指针,它们都按预期工作,所以我不明白为什么这行不通。如果能帮助理解这一点,我们将不胜感激。
谢谢。
让我们来看看一段代码的原始版本和修改版本,explain everything that's happening here to your rubber duck:
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
之前调用leftRotate
旋转node
,旋转后的node
从这个函数返回(node
是此函数的参数)。这就是您描述橡皮鸭这里发生的事情的方式。
现在,让我们试着向你的橡皮鸭解释这段代码的修改版本:
// Right Right Case
if (balance < -1 && key > node->right->key)
leftRotate(node); //CHANGED
你看,Rubber Duck 先生,leftRotate
被调用,它修改了通过引用传递的参数与原始版本 leftRotate
() 返回的参数,就是这样!
你的橡皮鸭现在会指出你的问题并说:“很好!但是你现在应该注意到一个明显的区别:leftRotate
() 最初返回的值,现在是新的 node
、 不再从此函数 return
ed 。代码的“更改”版本是在逻辑上不等同于原始版本!"
看看你的橡皮鸭有多大帮助?同样的逻辑错误在更改后的版本中多次出现,引用更改后的 leftRotate
和 rightRotate
.
我刚开始在我的数据结构和算法中学习 AVL 树 class。我在 Geeks for Geeks 上找到了将一个新节点插入树中并对其进行平衡的代码。代码如下所示。
// C++ program to insert a node in AVL tree
#include <iostream>
using namespace std;
// An AVL tree node
class Node
{
public:
int key;
Node *left;
Node *right;
int height;
};
// A utility function to get maximum
// of two integers
int max(int a, int b);
// A utility function to get the
// height of the tree
int height(Node *N)
{
if (N == NULL)
return 0;
return N->height;
}
// A utility function to get maximum
// of two integers
int max(int a, int b)
{
return (a > b)? a : b;
}
/* Helper function that allocates a
new node with the given key and
NULL left and right pointers. */
Node* newNode(int key)
{
Node* node = new Node();
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially
// added at leaf
return(node);
}
// A utility function to right
// rotate subtree rooted with y
// See the diagram given above.
Node *rightRotate(Node *y)
{
Node *x = y->left;
Node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left),
height(y->right)) + 1;
x->height = max(height(x->left),
height(x->right)) + 1;
// Return new root
return x;
}
// A utility function to left
// rotate subtree rooted with x
// See the diagram given above.
Node *leftRotate(Node *x)
{
Node *y = x->right;
Node *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left),
height(x->right)) + 1;
y->height = max(height(y->left),
height(y->right)) + 1;
// Return new root
return y;
}
// Get Balance factor of node N
int getBalance(Node *N)
{
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
// Recursive function to insert a key
// in the subtree rooted with node and
// returns the new root of the subtree.
Node* insert(Node* node, int key)
{
/* 1. Perform the normal BST insertion */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
else // Equal keys are not allowed in BST
return node;
/* 2. Update height of this ancestor node */
node->height = 1 + max(height(node->left),
height(node->right));
/* 3. Get the balance factor of this ancestor
node to check whether this node became
unbalanced */
int balance = getBalance(node);
// If this node becomes unbalanced, then
// there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node->left->key)
{
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node->right->key)
{
node->right = rightRotate(node->right);
return leftRotate(node);
}
/* return the (unchanged) node pointer */
return node;
}
// A utility function to print preorder
// traversal of the tree.
// The function also prints height
// of every node
void preOrder(Node *root)
{
if(root != NULL)
{
cout << root->key << " ";
preOrder(root->left);
preOrder(root->right);
}
}
// Driver Code
int main()
{
Node *root = NULL;
/* Constructing tree given in
the above figure */
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
/* The constructed AVL Tree would be
30
/ \
20 40
/ \ \
10 25 50
*/
cout << "\n\n" << "Preorder traversal of the "
"constructed AVL tree is \n";
preOrder(root);
cout << "\n\n";
return 0;
}
// This code is contributed by
// rathbhupendra
我理解代码是如何工作的(至少我认为是这样)。我稍微编辑了代码以尝试稍微不同的方法。对于 leftRotate 和 rightRotate 函数,最初,它们将指针作为参数,return 旋转后的指针 ("Node *leftRotate(Node *x)")。我试图通过引用指针参数和 return 类型 void ("void leftRotate(Node*& x)") 传递来改变它。代码如下所示(我在我更改原始代码的所有地方旁边添加了注释“//CHANGED”)。
// C++ program to insert a node in AVL tree
#include <iostream>
using namespace std;
// An AVL tree node
class Node
{
public:
int key;
Node *left;
Node *right;
int height;
};
// A utility function to get maximum
// of two integers
int max(int a, int b);
// A utility function to get the
// height of the tree
int height(Node *N)
{
if (N == NULL)
return 0;
return N->height;
}
// A utility function to get maximum
// of two integers
int max(int a, int b)
{
return (a > b)? a : b;
}
/* Helper function that allocates a
new node with the given key and
NULL left and right pointers. */
Node* newNode(int key)
{
Node* node = new Node();
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially
// added at leaf
return(node);
}
// A utility function to right
// rotate subtree rooted with y
// See the diagram given above.
void rightRotate(Node*& y) //CHANGED
{
Node *x = y->left;
Node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left),
height(y->right)) + 1;
x->height = max(height(x->left),
height(x->right)) + 1;
// Return new root
//return x; //CHANGED
}
// A utility function to left
// rotate subtree rooted with x
// See the diagram given above.
void leftRotate(Node*& x) //CHANGED
{
Node *y = x->right;
Node *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left),
height(x->right)) + 1;
y->height = max(height(y->left),
height(y->right)) + 1;
// Return new root
//return y; //CHANGED
}
// Get Balance factor of node N
int getBalance(Node *N)
{
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
// Recursive function to insert a key
// in the subtree rooted with node and
// returns the new root of the subtree.
Node* insert(Node* node, int key)
{
/* 1. Perform the normal BST insertion */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
else // Equal keys are not allowed in BST
return node;
/* 2. Update height of this ancestor node */
node->height = 1 + max(height(node->left),
height(node->right));
/* 3. Get the balance factor of this ancestor
node to check whether this node became
unbalanced */
int balance = getBalance(node);
// If this node becomes unbalanced, then
// there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
rightRotate(node); //CHANGED
// Right Right Case
if (balance < -1 && key > node->right->key)
leftRotate(node); //CHANGED
// Left Right Case
if (balance > 1 && key > node->left->key)
{
leftRotate(node->left); //CHANGED
rightRotate(node); //CHANGED
}
// Right Left Case
if (balance < -1 && key < node->right->key)
{
rightRotate(node->right); //CHANGED
leftRotate(node); //CHANGED
}
/* return the (unchanged) node pointer */
return node;
}
// A utility function to print preorder
// traversal of the tree.
// The function also prints height
// of every node
void preOrder(Node *root)
{
if(root != NULL)
{
cout << root->key << " ";
preOrder(root->left);
preOrder(root->right);
}
}
// Driver Code
int main()
{
Node *root = NULL;
/* Constructing tree given in
the above figure */
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
/* The constructed AVL Tree would be
30
/ \
20 40
/ \ \
10 25 50
*/
cout << "\n\n" << "Preorder traversal of the "
"constructed AVL tree is \n";
preOrder(root);
cout << "\n\n";
return 0;
}
// This code is contributed by
// rathbhupendra
我这样做的逻辑是,我可以通过引用传递指针,而不是 return 旋转指针,允许函数对指针本身进行旋转,而不是对指针的副本进行旋转指针。但是,当我 运行 这段代码时,我得到分段错误或只是没有输出(在 GeeksforGeeks 编码环境中它的分段错误和在 VS 代码上它只是没有输出)。有没有我也应该改变的东西,或者我只是做错了。我之前在以前的代码中通过引用传递指针,它们都按预期工作,所以我不明白为什么这行不通。如果能帮助理解这一点,我们将不胜感激。
谢谢。
让我们来看看一段代码的原始版本和修改版本,explain everything that's happening here to your rubber duck:
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
之前调用leftRotate
旋转node
,旋转后的node
从这个函数返回(node
是此函数的参数)。这就是您描述橡皮鸭这里发生的事情的方式。
现在,让我们试着向你的橡皮鸭解释这段代码的修改版本:
// Right Right Case
if (balance < -1 && key > node->right->key)
leftRotate(node); //CHANGED
你看,Rubber Duck 先生,leftRotate
被调用,它修改了通过引用传递的参数与原始版本 leftRotate
() 返回的参数,就是这样!
你的橡皮鸭现在会指出你的问题并说:“很好!但是你现在应该注意到一个明显的区别:leftRotate
() 最初返回的值,现在是新的 node
、 不再从此函数 return
ed 。代码的“更改”版本是在逻辑上不等同于原始版本!"
看看你的橡皮鸭有多大帮助?同样的逻辑错误在更改后的版本中多次出现,引用更改后的 leftRotate
和 rightRotate
.