首先定义节点:
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
class Node
{
public:
Node(int d);
Node(Node* other);
int data;
int height;
int distance;
Node* leftChild;
Node* rightChild;
Node* father;
int calculateDistance();
int calculateheight();
};
Node::Node(int d)
{
this->data = d;
father = NULL;
leftChild = NULL;
rightChild = NULL;
height = 1;
distance = 0;
}
Node::Node(Node* other)
{
this->data = other->data;
this->distance = other->distance;
this->father = other->father;
this->height = other->height;
this->leftChild = other->leftChild;
this->rightChild = other->rightChild;
}
int Node::calculateDistance()
{
int leftHeight;
int rightHeight;
leftHeight = leftChild == NULL? 0 : leftChild->height;
rightHeight = rightChild == NULL? 0 : rightChild->height;
return leftHeight-rightHeight;
}
int Node::calculateheight()
{
int leftHeight;
int rightHeight;
leftHeight = leftChild == NULL? 0 : leftChild->height;
rightHeight = rightChild == NULL? 0 : rightChild->height;
if(leftHeight > rightHeight)
return leftHeight+1;
else
return rightHeight+1;
}
这里有计算左右子树高度差的函数,左子树高度-右子树的高度。
还有计算该节点在树中的高度,在左右子树的更高者的基础上加1。
然后定义二叉平衡树:
#include"Node.h"
class Tree
{
public:
Tree();
void insert(int data);
bool delete_node(int data);
int size();
void display();
private:
void right_rotate(Node* target);
void left_rotate(Node* target);
void pre_order(Node* cur);
Node* root;
int count;
};
Tree::Tree()
{
root = NULL;
count = 0;
}
void Tree::insert(int data)
{
if(root == NULL)
root = new Node(data);
else
{
Node* current = root;
Node* pre = NULL;
while(current != NULL)
{
pre = current;
if(data <= current->data)
current = current->leftChild;
else
current = current->rightChild;
}
Node* newNode = new Node(data);
if(data <= pre->data)
pre->leftChild = newNode;
else
pre->rightChild = newNode;
newNode->father = pre;
Node* fatherNode = pre;
current = newNode;
while(pre != NULL)
{
pre->height = pre->calculateheight();
pre->distance = pre->calculateDistance();
if(pre->distance == 2)
{
if(pre->leftChild->distance == 1)
{
right_rotate(pre);
pre = pre->father;
}
if(pre->leftChild->distance == -1)
{
left_rotate(pre->leftChild);
right_rotate(pre);
pre = pre->father;
}
// pre = pre->father;
}
if(pre->distance == -2)
{
if(pre->rightChild->distance == -1)
{
left_rotate(pre);
pre = pre->father;
}
if(pre->rightChild->distance == 1)
{
right_rotate(pre->rightChild);
left_rotate(pre);
pre = pre->father;
}
}
current = pre;
pre = pre->father;
}
}
count++;
}
void Tree::left_rotate(Node* target)
{
Node* tempUp = target->rightChild;
Node* tempLeft2Right = tempUp->leftChild;
Node* top = target->father;
Node* up = new Node(tempUp);
if(tempUp->leftChild != NULL)
tempUp->leftChild->father = up;
if(tempUp->rightChild != NULL)
tempUp->rightChild->father = up;
Node* left2right;
if(tempLeft2Right != NULL)
{
left2right = new Node(tempLeft2Right);
if(tempLeft2Right->leftChild != NULL)
tempLeft2Right->leftChild->father = left2right;
if(tempLeft2Right->rightChild != NULL)
tempLeft2Right->rightChild->father = left2right;
}
else
left2right = NULL;
if(top != NULL)
{
if(top->leftChild == target)
top->leftChild = up;
else
top->rightChild = up;
}
up->father = top;
up->leftChild = target;
target->father = up;
target->rightChild = left2right;
if(left2right != NULL)
left2right->father = target;
target->height = target->calculateheight();
target->distance = target->calculateDistance();
up->height = up->calculateheight();
up->distance = up->calculateDistance();
top->height = top->calculateheight();
top->distance = top->calculateDistance();
delete(tempUp);
delete(tempLeft2Right);
// target = target->father;
}
void Tree::right_rotate(Node* target)
{
Node* tempUp = target->leftChild;
Node* tempRight2Left = tempUp->rightChild;
Node* top = target->father;
Node* up = new Node(tempUp);
if(tempUp->leftChild != NULL)
tempUp->leftChild->father = up;
if(tempUp->rightChild != NULL)
tempUp->rightChild->father = up;
Node* right2left;
if(tempRight2Left != NULL)
{
right2left = new Node(tempRight2Left);
if(tempRight2Left->leftChild != NULL)
tempRight2Left->leftChild->father = right2left;
if(tempRight2Left->rightChild != NULL)
tempRight2Left->rightChild->father = right2left;
}
else
right2left = NULL;
if(top != NULL)
{
if(top->leftChild == target)
top->leftChild = up;
else
top->rightChild = up;
}
up->father = top;
up->rightChild = target;
target->father = up;
target->leftChild = right2left;
if(right2left != NULL)
right2left->father = target;
target->height = target->calculateheight();
target->distance = target->calculateDistance();
up->height = up->calculateheight();
up->distance = up->calculateDistance();
top->height = top->calculateheight();
top->distance = top->calculateDistance();
delete(tempUp);
delete(tempRight2Left);
}
int Tree::size()
{
return count;
}
void Tree::display()
{
pre_order(root);
}
void Tree::pre_order(Node* cur)
{
if(cur != NULL)
{
pre_order(cur->leftChild);
printf("%d\n", cur->data);
pre_order(cur->rightChild);
}
}
二叉平衡树的关键是,它能够在插入所有元素之后保持平衡,左右子树的高度差不会超过1。所以在每次插入完元素后,检查二叉平衡树是否平衡。只要从插入点开始检查,一直往树的根端检查即可。(其实只需检查一个点)然后确定需要哪种旋转,是单旋转还是双旋转。这里,我用了新的指针来代表旋转所得的新位置。注意指针的指向的改变。