【发布时间】:2017-04-21 09:23:10
【问题描述】:
所以,我正在为一个项目编写一个自平衡二叉搜索树,我似乎遇到了插入函数的问题。具体来说,这里的这段代码:
if(element > n->data)
{
n->rightChild = insert(n->rightChild, element);
}
出于测试的目的,我只是使用 insert(root, 10) insert(root, 20) insert(root, 30) 等等。问题发生在插入 30 处。它通过并尝试用另一个非空子树替换一个非空子树(20)。我不确定为什么我似乎遇到了这个问题,因为递归是我看到它实现的唯一方法,在我发现的所有其他类似问题中,答案都是以类似的方式编码的到此或与此完全相同。谁能帮我弄清楚发生了什么?目前,在它尝试用 30 覆盖 20 子树后,它最终用垃圾数据填充根右子树,然后,当它尝试重新平衡时,抛出一个 EXC_BAD_ACCESS 错误,大概是因为我试图访问一个没有不存在。
源代码
#include <iostream>
using namespace std;
struct node
{
public:
int data, height;
node *leftChild, *rightChild;
};
int findMin(struct node *p) // finds the smallest node in the tree
{
while (p->leftChild != NULL)
p = p->leftChild;
return p->data;
}
int findMax(struct node *p) // finds the largest node in the tree
{
while(p->rightChild != NULL)
p = p->rightChild;
return p->data;
}
int max(int a, int b) // gets the max of two integers
{
if(a > b)
return a;
else
return b;
}
int height(struct node *p) // gets the height of the tree
{
int lHeight, rHeight;
if(p == NULL)
return -1;
else
{
lHeight = height(p->leftChild);
rHeight = height(p->rightChild);
if(lHeight > rHeight)
return lHeight + 1;
else
return rHeight + 1;
}
}
struct node* newNode(int element) // helper function to return a new node with empty subtrees
{
node* newPtr = (struct node*) malloc(sizeof(newPtr));
newPtr->data = element;
newPtr->leftChild = NULL;
newPtr->rightChild = NULL;
newPtr->height = 1;
return newPtr;
}
struct node* rightRotate(struct node* p) // function to right rotate a tree rooted at p
{
node* child = p->leftChild;
node* grandChild = child->rightChild;
// perform the rotation
child->rightChild = p;
p->leftChild = grandChild;
// update the height for the nodes
p->height = max(height(p->leftChild), height(p->rightChild)) + 1;
child->height = max(height(child->leftChild), height(child->rightChild)) + 1;
// return new root
return child;
}
struct node* leftRotate(struct node* p) // function to left rotate a tree rooted at p
{
node* child = p->rightChild;
node* grandChild = child->leftChild;
// perform the rotation
child->leftChild = p;
p->rightChild = grandChild;
// update heights
p->height = max(height(p->leftChild), height(p->rightChild)) + 1;
// return new root
return child;
}
int getBalance(struct node *p)
{
if(p == NULL)
return 0;
else
return height(p->leftChild) - height(p->rightChild);
}
// recursive version of BST insert to insert the element in a sub tree rooted with root
// which returns new root of subtree
struct node* insert(struct node*& n, int element)
{
// perform the normal BST insertion
if(n == NULL) // if the tree is empty
return(newNode(element));
if(element< n->data)
{
n->leftChild = insert(n->leftChild, element);
}
if(element > n->data)
{
n->rightChild = insert(n->rightChild, element);
}
else // duplicate node
{
return n;
}
// update the height for this node
n->height = 1 + max(height(n->leftChild), height(n->rightChild));
// get the balance factor to see if the tree is unbalanced
int balance = getBalance(n);
// the tree is unbalanced, there are 4 different types of rotation to make
// Single Right Rotation (Left Left Case)
if(balance > 1 && element < n->leftChild->data)
{
return rightRotate(n);
}
// Single Left Rotation (Right Right Case)
if(balance < -1 && element > n->rightChild->data)
{
return leftRotate(n);
}
// Left Right Rotation
if(balance > 1 && element > n->leftChild->data)
{
n->leftChild = leftRotate(n->leftChild);
return rightRotate(n);
}
// Right Left Rotation
if(balance < -1 && element < n->rightChild->data)
{
n->rightChild = rightRotate(n->rightChild);
return leftRotate(n);
}
cout << "Height: " << n->height << endl;
// return the unmodified root pointer in the case that the tree does not become unbalanced
return n;
}
void inorder(struct node *p)
{
if(p != NULL)
{
inorder(p->leftChild);
cout << p->data << ", ";
inorder(p->rightChild);
}
}
void preorder(struct node *p)
{
if(p != NULL)
{
cout << p->data << ", ";
preorder(p->leftChild);
preorder(p->rightChild);
}
}
void print(struct node* root)
{
cout << "Min Value: " << findMin(root) << endl;
cout << "Max Value: " << findMax(root) << endl;
cout << "Pre Order: ";
preorder(root);
cout << "Inorder: ";
inorder(root);
}
int main()
{
struct node* root = NULL;
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
// int array[11] = {25, 5, 6, 17, 34, 2, 57, 89, 12, 12, 73};
// for(int i = 0; i < 11; i++)
// {
// root = insert(root, array[i]);
// }
preorder(root);
return 0;
}
【问题讨论】:
-
为什么在 C++ 程序中使用
malloc?使用new分配内存。另外,为什么到处都是struct node *?对于 C++,您只需指定node。似乎您正在阅读C材料而不是C++。 -
顺便说一句,你说的完全正确,我不需要这些。谢谢
标签: c++ insert binary-search-tree