如何解决C ++平衡AVL树
我正在用c ++实现bst,更确切地说是AVL树。除了平衡以外,我几乎可以进行所有工作。当程序尝试平衡LR或RL时,它将崩溃。例如,如果在我插入7、5、6或7、9、8时崩溃,但是它将与:7、6、5和7、8、9一起工作。
相关代码(pastebin):https://pastebin.com/cn69XLn5
相关代码:
//RIGHT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RRrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->rightChild;
rootptr->rightChild = temp->leftChild;
temp->leftChild = rootptr;
return temp;
}
//LEFT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LLrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->leftChild;
rootptr->leftChild = temp->rightChild;
temp->rightChild = rootptr;
return temp;
}
//LEFT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LRrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->leftChild;
rootptr->leftChild = RRrotation(temp);
return LLrotation(rootptr);
}
//RIGHT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RLrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->rightChild;
rootptr->rightChild = LLrotation(temp);
return RRrotation(rootptr);
}
// There are four different rotation scenarios,two simpler and two harder.
// check what rotation is needed and then send forward to that rotation
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::balanceFactory(bstNode* rootptr)
{
//std::cout << rootptr->value << std::endl;
int BF = balanceFactor();
if (BF > 1) //use == 2 instead?
{
if (balanceFactorLeftChild() > 0) //perform left left rotation
{
rootptr = LLrotation(rootptr);
}else //perform left right rotation
{
rootptr = LRrotation(rootptr);
}
}
else if (BF < -1)
{
if (balanceFactorRightChild() > 0) // perform right left rotation
{
rootptr = RLrotation(rootptr);
}else
{
rootptr = RRrotation(rootptr); // the last option,which is right right rotation
}
}
return rootptr;
}
template <typename x_type>
void AVLTree<x_type>::insert(x_type value){
insert(&(this->rootptr),value);
}
template <typename x_type>
void AVLTree<x_type>::insert(bstNode** rootptr,x_type value)
{
if (*rootptr == nullptr)
{
//this tree is empty
*rootptr = createNewNode(value);
}
else if ((*rootptr)->value == value) //if value already in tree,dont insert again,just break
{
return;
}else if (value <= (*rootptr)->value)
{
//insert at left side using recursion
insert(&(*rootptr)->leftChild,value);
*rootptr = balanceFactory(*rootptr);
}else if (value >= (*rootptr)->value)
{
//insert at right side using recursion
insert(&(*rootptr)->rightChild,value);
*rootptr = balanceFactory(*rootptr);
}
}
所有代码(pastebin):https://pastebin.com/uxTQ369i
所有代码:
//avl tree emil wallin
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
template <typename x_type>
class AVLTree {
struct bstNode {
x_type value;
bstNode* leftChild;
bstNode* rightChild;
};
//bstNode* rootptr;
public:
AVLTree();
bstNode* createNewNode(x_type value);
int balanceFactor();
int balanceFactorLeftChild();
int balanceFactorRightChild();
bstNode* RRrotation(bstNode* rootptr);
bstNode* LLrotation(bstNode* rootptr);
bstNode* LRrotation(bstNode* rootptr);
bstNode* RLrotation(bstNode* rootptr);
bstNode* balanceFactory(bstNode* rootptr);
void insert(x_type value);
void remove(x_type value);
bool find(x_type value);
std::vector<x_type>preOrderWalk();
std::vector<x_type>inorderWalk();
std::vector<x_type>postorderWalk();
x_type getMin();
x_type getMax();
x_type maxVal(x_type a,x_type b);
size_t getTreeHeight();
bstNode* get_rootptr(){return rootptr;}
private:
bstNode* rootptr;
int balanceFactor(bstNode* rootptr);
void insert(bstNode** rootptr,x_type value);
void remove(bstNode*,x_type value);
bool find(bstNode* rootptr,x_type value);
std::vector<x_type> preOrderWalk(bstNode* rootptr);
std::vector<x_type> inorderWalk(bstNode* rootptr);
std::vector<x_type> postorderWalk(bstNode* rootptr);
x_type getMin(bstNode* rootptr);
x_type getMax(bstNode* rootptr);
size_t getTreeHeight(bstNode* rootptr);
};
//this is a constructor:
template <typename x_type>
AVLTree<x_type>::AVLTree()
{
this->rootptr = nullptr;
}
//dynamically allocate new memory for a node,using keyword new
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::createNewNode(x_type value)
{
bstNode* newNode = new bstNode();
(*newNode).value = value;
newNode->leftChild = nullptr;
newNode->rightChild = nullptr;
return newNode;
}
template <typename x_type>
int AVLTree<x_type>::balanceFactorLeftChild()
{
return balanceFactor(this->rootptr->leftChild);
}
template <typename x_type>
int AVLTree<x_type>::balanceFactorRightChild()
{
return balanceFactor(this->rootptr->rightChild);
}
template <typename x_type>
int AVLTree<x_type>::balanceFactor()
{
return balanceFactor(this->rootptr);
}
template <typename x_type>
int AVLTree<x_type>::balanceFactor(bstNode* rootptr)
{
int leftHeight = getTreeHeight(rootptr->leftChild);
int rightHeight = getTreeHeight(rootptr->rightChild);
int balanceNumber = leftHeight - rightHeight;
return balanceNumber;
}
//RIGHT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RRrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->rightChild;
rootptr->rightChild = temp->leftChild;
temp->leftChild = rootptr;
return temp;
}
//LEFT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LLrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->leftChild;
rootptr->leftChild = temp->rightChild;
temp->rightChild = rootptr;
return temp;
}
//LEFT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LRrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->leftChild;
rootptr->leftChild = RRrotation(temp);
return LLrotation(rootptr);
}
//RIGHT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RLrotation(bstNode* rootptr)
{
bstNode* temp;
temp = rootptr->rightChild;
rootptr->rightChild = LLrotation(temp);
return RRrotation(rootptr);
}
// There are four different rotation scenarios,which is right right rotation
}
}
return rootptr;
}
template <typename x_type>
void AVLTree<x_type>::insert(x_type value){
insert(&(this->rootptr),value);
}
template <typename x_type>
void AVLTree<x_type>::insert(bstNode** rootptr,x_type value)
{
if (*rootptr == nullptr)
{
//this tree is empty
*rootptr = createNewNode(value);
}
else if ((*rootptr)->value == value) //if value already in tree,just break
{
return;
}else if (value <= (*rootptr)->value)
{
//insert at left side using recursion
insert(&(*rootptr)->leftChild,value);
*rootptr = balanceFactory(*rootptr);
}else if (value >= (*rootptr)->value)
{
//insert at right side using recursion
insert(&(*rootptr)->rightChild,value);
*rootptr = balanceFactory(*rootptr);
}
}
template <typename x_type>
void AVLTree<x_type>::remove(x_type value)
{
remove(this->rootptr,value);
}
template <typename x_type>
void AVLTree<x_type>::remove(bstNode* rootptr,x_type value)
{
if (rootptr == nullptr)
{
return; //there is no data in tree
} else if (value > rootptr->value) // go to right subtree
{
remove(rootptr->rightChild,value);
} else if (value < rootptr->value) // go to left subtree
{
remove(rootptr->leftChild,value);
}
else // if its not greater nor less,it must be equal,therefore we found the node to be removed
{
//there are three different situations.
//the node we must remove can have 0 children -> 1.
//the node we must remove can have 1 child -> 2.
//the node we must remove can have 2 children -> 3.
//1:
if (rootptr->leftChild == nullptr && rootptr->rightChild == nullptr)
{
delete rootptr;
rootptr = nullptr;
}
//2:
else if (rootptr->leftChild == nullptr)
{
bstNode* tempPtr = rootptr;
rootptr = rootptr->rightChild;
delete tempPtr;
}
//2 (other child):
else if (rootptr->rightChild == nullptr)
{
bstNode* tempPtr = rootptr;
rootptr = rootptr->leftChild;
delete tempPtr;
}
//3:
else
{
//bstNode<x_type>* tempPtr = getMin(rootptr->rightChild);
bstNode* tempPtr = rootptr;
tempPtr->value = getMax(rootptr->leftChild);
rootptr->value = tempPtr->value;
remove(rootptr->leftChild,tempPtr->value);
}
}
return;
}
template <typename x_type>
bool AVLTree<x_type>::find(x_type value)
{
return find(this->rootptr,value);
}
template <typename x_type>
bool AVLTree<x_type>::find(bstNode* rootptr,x_type value)
{
if (rootptr == nullptr)
{
//either the tree is empty
return false;
}else if (rootptr->value == value)
{
//value found
return true;
}else if (value <= rootptr->value)
{
return find(rootptr->leftChild,value);
}else if (value >= rootptr->value)
{
return find(rootptr->rightChild,value);
}
return false;
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::preOrderWalk(){
return preOrderWalk(this->rootptr);
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::preOrderWalk(bstNode* rootptr)
{
std::vector<x_type> preOrderVec;
if (rootptr != nullptr)
{
std::vector<x_type> temp;
preOrderVec.push_back(rootptr->value);
if (rootptr->leftChild != nullptr)
{
temp = preOrderWalk(rootptr->leftChild); //mästarns notering
preOrderVec.insert(preOrderVec.end(),temp.begin(),temp.end());
}
if (rootptr->rightChild != nullptr)
{
temp = preOrderWalk(rootptr->rightChild);
preOrderVec.insert(preOrderVec.end(),temp.end());
}
}
return preOrderVec;
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::inorderWalk(){
return inorderWalk(this->rootptr);
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::inorderWalk(bstNode* rootptr)
{
std::vector<x_type> inorderVec;
if (rootptr != nullptr)
{
std::vector<x_type> temp;
if (rootptr->leftChild != nullptr)
{
temp = inorderWalk(rootptr->leftChild); //mästarns notering
inorderVec.insert(inorderVec.end(),temp.end());
}
inorderVec.push_back(rootptr->value);
if (rootptr->rightChild != nullptr)
{
temp = inorderWalk(rootptr->rightChild);
inorderVec.insert(inorderVec.end(),temp.end());
}
}
return inorderVec;
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::postorderWalk(){
return postorderWalk(this->rootptr);
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::postorderWalk(bstNode* rootptr)
{
std::vector<x_type> postorderVec;
if (rootptr != nullptr)
{
std::vector<x_type> temp;
if (rootptr->leftChild != nullptr)
{
temp = postorderWalk(rootptr->leftChild); //mästarns notering
postorderVec.insert(postorderVec.end(),temp.end());
}
if (rootptr->rightChild != nullptr)
{
temp = postorderWalk(rootptr->rightChild);
postorderVec.insert(postorderVec.end(),temp.end());
}
postorderVec.push_back(rootptr->value);
}
return postorderVec;
}
template <typename x_type>
x_type AVLTree<x_type>::getMin()
{
return (getMin(this->rootptr));
}
template <typename x_type>
x_type AVLTree<x_type>::getMin(bstNode* rootptr)
{
if (rootptr == nullptr) //empty tree
{
std::cout << "No minimum because the tree is empty" << std::endl;
}
else if(rootptr->leftChild == nullptr) //the node that has no leftChild must be the last we want to search
{
return rootptr->value;
}
return getMin(rootptr->leftChild);
}
template <typename x_type>
x_type AVLTree<x_type>::getMax()
{
return getMax(this->rootptr);
}
template <typename x_type>
x_type AVLTree<x_type>::getMax(bstNode* rootptr)
{
if (rootptr == nullptr) // empty tree
{
std::cout << "No maximum because the tree is empty" << std::endl;
}
else if(rootptr->rightChild == nullptr) //the node that has no rightChild must be the last we want to search
{
return rootptr->value;
}
return getMax(rootptr->rightChild);
}
template <typename x_type>
x_type AVLTree<x_type>::maxVal(x_type a,x_type b)
{
if (a > b) return a;
else return b;
}
template <typename x_type>
size_t AVLTree<x_type>::getTreeHeight()
{
return getTreeHeight(this->rootptr);
}
template <typename x_type>
size_t AVLTree<x_type>::getTreeHeight(bstNode* rootptr)
{
int height;
int leftHeight;
int rightHeight;
if (rootptr == nullptr) return -1;
leftHeight = getTreeHeight(rootptr->leftChild);
rightHeight = getTreeHeight(rootptr->rightChild);
height = (maxVal(leftHeight,rightHeight));
height += 1;
//static_cast<size_t>(height);
return height;
}
int main()
{
AVLTree<int>* avlTreeobject = new AVLTree<int>();
avlTreeobject->insert(7);
avlTreeobject->insert(6);
avlTreeobject->insert(5);
std::cout << "\n actual root: " << (avlTreeobject->get_rootptr()->value);
std::cout << "\n actual root->leftchild: " << (avlTreeobject->get_rootptr()->leftChild->value);
std::cout << "\n actual root->rightchild: " << (avlTreeobject->get_rootptr()->rightChild->value);
std::cin.get();
std::getchar();
return 0;
}
我不确定,但是我认为问题是我向该函数发送了错误的节点,因此它崩溃,因为它假定正在发送的节点将有一个子节点,但不会,因此它尝试访问nullptr。我不知道该如何解决
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。