英文:
Getting segmentation fault in a code of AVL tree
问题
我这里有一个AVL树的代码:
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct avl {
avl *left;
avl* right;
avl* parent;
int data;
} avl;
class AVL{
avl* root;
public:
void insert(int d);
void inorder(avl*);
void preorder();
void rr_rotation(avl*);
void ll_rotation(avl*, int);
void rl_rotation(avl*);
void lr_rotation(avl*);
int height(avl *t);
int getbalance(avl *parent);
void check_avl(avl*);
avl* getroot();
AVL(){
root=NULL;
}
};
avl* AVL::getroot(){
return root;
}
int AVL::height(avl *p){
int l_height=0, r_height=0;
int h=0;
if(p!=nullptr){
l_height=height(p->left);
r_height=height(p->right);
h= l_height>r_height ? l_height : r_height;
}
return ++h;
}
int AVL::getbalance(avl *p){
int l_height=0, r_height=0;
if(p!=nullptr){
l_height=height(p->left);
r_height=height(p->right);
}
int b= l_height-r_height;
return b;
}
void AVL:: rr_rotation(avl *tree){
cout<<"RR rotation"<<endl;
avl* t=tree->left;
t->right=tree;
if(root==tree)
root=t;
else{
tree=t;
}
}
void AVL:: ll_rotation(avl *tree, int l=0){
cout<<"LL rotation"<<endl;
avl* t=tree->right;
t->left=tree;
if(root==tree)
root=t;
else{
tree=t;
}
}
void AVL:: lr_rotation(avl *tree){
cout<<"LR rotation"<<endl;
ll_rotation(tree->left,1);
rr_rotation(tree);
}
void AVL:: rl_rotation(avl *tree){
cout<<"RL rotation"<<endl;
rr_rotation(tree->right);
ll_rotation(tree);
}
void AVL::insert(int d){
cout<<"Inserting "<<d<<endl;
int c=0;
avl *t = (avl*)malloc(sizeof(avl));
t->data=d;
t->parent=t->left=t->right=NULL;
if(root==NULL){
root=t;
}
else{
avl* tree;
avl* sample;
tree=root;
while(tree!=NULL){
if(d<tree->data){
sample=tree;
tree=tree->left;
c=1;
}
else{
sample=tree;
tree=tree->right;
c=2;
}
}
switch(c){
case 1:
sample->left=t;
(sample->left)->parent=sample;
break;
case 2:
sample->right=t;
t->parent=sample;
}
}
check_avl(root);
}
void AVL::check_avl(avl * t){
if(t!=NULL){
int balance=getbalance(t);
if(balance>1){
avl* child=t->left;
if((child!=NULL) && (child->left!=NULL))
rr_rotation(t);
else if((child!=NULL) && (child->right!=NULL))
lr_rotation(t);
}
else if(balance<-1){
avl* child=t->right;
if((child!=NULL) && (child->left!=NULL))
rl_rotation(t);
else if((child!=NULL) && (child->right!=NULL))
ll_rotation(t);
}
check_avl(t->left);
check_avl(t->right);
}
}
void AVL::inorder(avl* t){
if(t!=NULL){
inorder(t->left);
cout<<t->data<<" ";
inorder(t->right);
}
}
int main()
{
AVL a;
a.insert(10);
a.insert(6);
a.insert(3);
a.insert(20);
a.insert(15);
a.insert(8);
a.insert(5);
a.insert(9);
a.inorder(a.getroot());
}
我尝试插入3时,出现了分段错误。请帮我找出问题。
英文:
I have a code for AVL tree here:
#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct avl {
avl *left;
avl* right;
avl* parent;
int data;
} avl;
class AVL{
avl* root;
public:
void insert(int d);
void inorder(avl*);
void preorder();
void rr_rotation(avl*);
void ll_rotation(avl*, int);
void rl_rotation(avl*);
void lr_rotation(avl*);
int height(avl *t);
int getbalance(avl *parent);
void check_avl(avl*);
avl* getroot();
AVL(){
root=NULL;
}
};
avl* AVL::getroot(){
return root;
}
int AVL::height(avl *p){
int l_height=0, r_height=0;
int h=0;
if(p!=nullptr){
l_height=height(p->left);
r_height=height(p->right);
h= l_height>r_height ? l_height : r_height;
}
return ++h;
}
int AVL::getbalance(avl *p){
int l_height=0, r_height=0;
if(p!=nullptr){
l_height=height(p->left);
r_height=height(p->right);
}
int b= l_height-r_height;
return b;
}
void AVL:: rr_rotation(avl *tree){
cout<<"RR rotation"<<endl;
avl* t=tree->left;
t->right=tree;
if(root==tree)
root=t;
else{
tree=t;
}
}
void AVL:: ll_rotation(avl *tree, int l=0){
cout<<"LL rotation"<<endl;
avl* t=tree->right;
t->left=tree;
if(root==tree)
root=t;
else{
tree=t;
}
}
void AVL:: lr_rotation(avl *tree){
cout<<"LR rotation"<<endl;
ll_rotation(tree->left,1);
rr_rotation(tree);
}
void AVL:: rl_rotation(avl *tree){
cout<<"RL rotation"<<endl;
rr_rotation(tree->right);
ll_rotation(tree);
}
void AVL::insert(int d){
cout<<"Inserting "<<d<<endl;
int c=0;
avl *t = (avl*)malloc(sizeof(avl));
t->data=d;
//cout<<t->data;
t->parent=t->left=t->right=NULL;
if(root==NULL){
root=t;
}
else{
avl* tree;
avl* sample;
tree=root;
while(tree!=NULL){
if(d<tree->data){
sample=tree;
tree=tree->left;
c=1;
}
else{
sample=tree;
tree=tree->right;
c=2;
}
}
switch(c){
case 1:
sample->left=t;
(sample->left)->parent=sample;
break;
case 2:
sample->right=t;
t->parent=sample;
}
}
check_avl(root);
}
void AVL::check_avl(avl * t){
if(t!=NULL){
int balance=getbalance(t);
if(balance>1){
avl* child=t->left;
if((child!=NULL) && (child->left!=NULL))
rr_rotation(t);
else if((child!=NULL) && (child->right!=NULL))
lr_rotation(t);
}
else if(balance<-1){
avl* child=t->right;
if((child!=NULL) && (child->left!=NULL))
rl_rotation(t);
else if((child!=NULL) && (child->right!=NULL))
ll_rotation(t);
}
check_avl(t->left);
check_avl(t->right);
}
}
void AVL::inorder(avl* t){
if(t!=NULL){
inorder(t->left);
cout<<t->data<<" ";
inorder(t->right);
}
}
int main()
{
AVL a;
a.insert(10);
a.insert(6);
a.insert(3);
a.insert(20);
a.insert(15);
a.insert(8);
a.insert(5);
a.insert(9);
a.inorder(a.getroot());
}
When I'm trying to insert 3, I'm getting a segmentation fault.
Help to figure out my issue
答案1
得分: 1
你在进行旋转或插入节点时没有正确更新父节点指针。在旋转函数(rr_rotation
、ll_rotation
、lr_rotation
和 rl_rotation
)以及插入函数中,请正确更新父节点指针。
经过你所做的更改后的代码如下:
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct avl {
avl* left;
avl* right;
avl* parent;
int data;
} avl;
class AVL {
avl* root;
public:
void insert(int d);
void inorder(avl*);
void preorder();
void rr_rotation(avl*);
void ll_rotation(avl*); // changed from void ll_rotation(avl*, int);
void rl_rotation(avl*);
void lr_rotation(avl*);
int height(avl* t);
int getbalance(avl* parent);
void check_avl(avl*);
avl* getroot();
AVL() {
root = NULL;
}
};
avl* AVL::getroot() {
return root;
}
int AVL::height(avl* p) {
int l_height = 0, r_height = 0;
int h = 0;
if (p != nullptr) {
l_height = height(p->left);
r_height = height(p->right);
h = l_height > r_height ? l_height : r_height;
}
return ++h;
}
int AVL::getbalance(avl* p) {
int l_height = 0, r_height = 0;
if (p != nullptr) {
l_height = height(p->left);
r_height = height(p->right);
}
int b = l_height - r_height;
return b;
}
/* 当我们将左子树 t 移动到替换原始节点树时,
我们需要更新新树的左子树的父指针和树本身的父指针。 */
void AVL::rr_rotation(avl* tree) {
cout << "RR rotation" << endl;
avl* t = tree->left;
tree->left = t->right;
if (t->right != NULL) {
t->right->parent = tree; // 修正:更新右子树的父指针
}
t->right = tree;
t->parent = tree->parent;
tree->parent = t;
if (root == tree)
root = t;
else {
if (t->parent->left == tree)
t->parent->left = t;
else
t->parent->right = t;
}
}
/* 当我们将右子树 t 移动到替换原始节点树时,
我们需要更新新树的右子树的父指针和树本身的父指针。 */
void AVL::ll_rotation(avl* tree) {
cout << "LL rotation" << endl;
avl* t = tree->right;
tree->right = t->left;
if (t->left != NULL) {
tree->left->parent = tree; // 修正:更新左子树的父指针
}
t->left = tree;
t->parent = tree->parent;
tree->parent = t;
if (root == tree)
root = t;
else {
if (t->parent->left == tree)
t->parent->left = t;
else
t->parent->right = t;
}
}
void AVL::lr_rotation(avl* tree) {
cout << "LR rotation" << endl;
ll_rotation(tree->left);
rr_rotation(tree);
}
void AVL::rl_rotation(avl* tree) {
cout << "RL rotation" << endl;
rr_rotation(tree->right);
ll_rotation(tree);
}
void AVL::insert(int d) {
cout << "Inserting " << d << endl;
int c = 0;
avl* t = new avl; // 改为 new (c++ 风格)
t->data = d;
t->parent = t->left = t->right = NULL;
if (root == NULL) {
root = t;
}
else {
avl* tree;
avl* sample;
tree = root;
while (tree != NULL) {
sample = tree; // 它曾经在 if (d < tree->data) 中
if (d < tree->data) {
tree = tree->left;
c = 1;
}
else {
tree = tree->right;
c = 2;
}
}
switch (c) {
case 1:
sample->left = t; // 不需要第二行 (sample->left)->parent=sample;
break;
case 2:
sample->right = t;
break;
}
t->parent = sample;
}
check_avl(root);
}
void AVL::check_avl(avl* t) {
if (t != NULL) {
int balance = getbalance(t);
if (balance > 1) {
avl* child = t->left;
if (child != NULL && getbalance(child) >= 0) // 替换为 getbalance
rr_rotation(t);
else if (child != NULL && getbalance(child) < 0) // 替换为 getbalance
lr_rotation(t);
}
else if (balance < -1) {
avl* child = t->right;
if (child != NULL && getbalance(child) <= 0) // 替换为 getbalance
ll_rotation(t);
else if (child != NULL && getbalance(child) > 0) // 替换为 getbalance
rl_rotation(t);
}
check_avl(t->left);
check_avl(t->right);
}
}
void AVL::inorder(avl* t) {
if (t != NULL) {
inorder(t->left);
cout << t->data << " ";
inorder(t->right);
}
}
int main() {
AVL a;
a.insert(10);
a.insert(6);
a.insert(3);
a.insert(20);
a.insert(15);
a.insert(8);
a.insert(5);
a.insert(9);
a.inorder(a.getroot());
return 0;
}
输出:
Inserting 10
Inserting 6
Inserting 3
RR rotation
Inserting 20
Inserting 15
LL rotation
Inserting 8
Inserting 5
Inserting 9
3 5 6 8 9 10 15 20
英文:
You are not properly updating the parent pointer when performing rotations or inserting nodes.
Update the parent pointers correctly in your rotation functions (rr_rotation
, ll_rotation
, lr_rotation
, and rl_rotation
) as well as when inserting nodes in the insert function.
Here is the code after the changes that I made:
#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct avl {
avl* left;
avl* right;
avl* parent;
int data;
} avl;
class AVL {
avl* root;
public:
void insert(int d);
void inorder(avl*);
void preorder();
void rr_rotation(avl*);
void ll_rotation(avl*); // changed from void ll_rotation(avl*, int);
void rl_rotation(avl*);
void lr_rotation(avl*);
int height(avl* t);
int getbalance(avl* parent);
void check_avl(avl*);
avl* getroot();
AVL() {
root = NULL;
}
};
avl* AVL::getroot() {
return root;
}
int AVL::height(avl* p) {
int l_height = 0, r_height = 0;
int h = 0;
if (p != nullptr) {
l_height = height(p->left);
r_height = height(p->right);
h = l_height > r_height ? l_height : r_height;
}
return ++h;
}
int AVL::getbalance(avl* p) {
int l_height = 0, r_height = 0;
if (p != nullptr) {
l_height = height(p->left);
r_height = height(p->right);
}
int b = l_height - r_height;
return b;
}
/* when we move the left child t up to replace the original node tree,
we need to update the parent pointers of the left child of the
new tree and the parent pointer of tree itself. */
void AVL::rr_rotation(avl* tree) {
cout << "RR rotation" << endl;
avl* t = tree->left;
tree->left = t->right;
if (t->right != NULL) {
t->right->parent = tree; // Fix: Update parent pointer of the right child
}
t->right = tree;
t->parent = tree->parent;
tree->parent = t;
if (root == tree)
root = t;
else {
if (t->parent->left == tree)
t->parent->left = t;
else
t->parent->right = t;
}
}
/* when we move the right child t up to replace the original node tree,
we need to update the parent pointers of the right child of the
new tree and the parent pointer of tree itself. */
void AVL::ll_rotation(avl* tree) {
cout << "LL rotation" << endl;
avl* t = tree->right;
tree->right = t->left;
if (t->left != NULL) {
tree->left->parent = tree; // Fix: Update parent pointer of the left child
}
t->left = tree;
t->parent = tree->parent;
tree->parent = t;
if (root == tree)
root = t;
else {
if (t->parent->left == tree)
t->parent->left = t;
else
t->parent->right = t;
}
}
void AVL::lr_rotation(avl* tree) {
cout << "LR rotation" << endl;
ll_rotation(tree->left);
rr_rotation(tree);
}
void AVL::rl_rotation(avl* tree) {
cout << "RL rotation" << endl;
rr_rotation(tree->right);
ll_rotation(tree);
}
void AVL::insert(int d) {
cout << "Inserting " << d << endl;
int c = 0;
avl* t = new avl; // changed to new (c++ style)
t->data = d;
t->parent = t->left = t->right = NULL;
if (root == NULL) {
root = t;
}
else {
avl* tree;
avl* sample;
tree = root;
while (tree != NULL) {
sample = tree; // it was in if (d < tree->data)
if (d < tree->data) {
tree = tree->left;
c = 1;
}
else {
tree = tree->right;
c = 2;
}
}
switch (c) {
case 1:
sample->left = t; // no need second line (sample->left)->parent=sample;
break;
case 2:
sample->right = t;
break;
}
t->parent = sample;
}
check_avl(root);
}
void AVL::check_avl(avl* t) {
if (t != NULL) {
int balance = getbalance(t);
if (balance > 1) {
avl* child = t->left;
if (child != NULL && getbalance(child) >= 0) // replaced with getbalance
rr_rotation(t);
else if (child != NULL && getbalance(child) < 0) // replaced with getbalance
lr_rotation(t);
}
else if (balance < -1) {
avl* child = t->right;
if (child != NULL && getbalance(child) <= 0) // replaced with getbalance
ll_rotation(t);
else if (child != NULL && getbalance(child) > 0) // replaced with getbalance
rl_rotation(t);
}
check_avl(t->left);
check_avl(t->right);
}
}
void AVL::inorder(avl* t) {
if (t != NULL) {
inorder(t->left);
cout << t->data << " ";
inorder(t->right);
}
}
int main() {
AVL a;
a.insert(10);
a.insert(6);
a.insert(3);
a.insert(20);
a.insert(15);
a.insert(8);
a.insert(5);
a.insert(9);
a.inorder(a.getroot());
return 0;
}
Output:
Inserting 10
Inserting 6
Inserting 3
RR rotation
Inserting 20
Inserting 15
LL rotation
Inserting 8
Inserting 5
Inserting 9
3 5 6 8 9 10 15 20
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论