特点:平衡二叉树要求对于每一个节点来说,他的左右子树的高度之差不超过1,如果插入或者删除一个结点使得高度之差大于1,就要进行节点之间的旋转(左旋或者右旋),将二叉树重新维持在一个平衡状态。
解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最坏和最好情况都维持在O(logN)。
旋转缺点:频繁旋转会牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了许多。
平衡二叉树的核心:
旋转算法
1:左左形式的不平衡
2.左右形式的不平衡
3.右左形式的不平衡
4.右右形式的不平衡
1,4一组
2,3一组
对于1:左旋 3的右子树给6的左边,6变成3的右子树,3成根
确定要换的根root和左子树left,left的右子树给root的左,root变成left的右
对于4:右旋 4的左子树给2的右边,2变成4的左子树,2成根
确定要换的根root和右子树right,right的左子树给root的右然后root变成right的左
对于2:先右旋左子树,再左旋根
对于3:先左旋右子书,再右旋根
代码如下:
#include <iostream>
#include <malloc.h>
#include <stack>
using namespace std;
typedef struct TreeNode
{
int height;
int data;
TreeNode* leftC;
TreeNode* rightC;
}TreeNode;
int getHeight(TreeNode* s)
{
if (s != NULL)
{
return s->height;
}
return -1;
}
void InitTree(TreeNode** list)
{
*list = (TreeNode*)malloc(sizeof(TreeNode));
(*list)->height = 0;
(*list)->leftC = NULL;
(*list)->rightC = NULL;
}
void leftRotate(TreeNode*& root)//左左
{
TreeNode *l1 = root;
TreeNode *l2 = root->leftC;
l1->leftC = l2->rightC;
l2->rightC = l1;
l1->height = (getHeight(l1->leftC) > getHeight(l1->rightC) ? getHeight(l1->leftC) : getHeight(l1->rightC)) + 1;
l2->height = (getHeight(l2->leftC) > getHeight(l2->rightC) ? getHeight(l2->leftC) : getHeight(l2->rightC)) + 1;
root = l2;
}
void rightRotate(TreeNode*& root)//右右
{
TreeNode *l1 = root;
TreeNode *l2 = root->rightC;
l1->rightC = l2->leftC;
l2->leftC = l1;
l1->height = getHeight(l1);
l2->height = getHeight(l2);
root = l2;
}
///左右,先右旋,再左旋
void DoubleRotateLR(TreeNode* &n1)
{
rightRotate(n1->leftC);
leftRotate(n1);
}
//右左,先左旋,后右旋
void DoubleRotateRL(TreeNode* &n1)
{
leftRotate(n1->rightC);
rightRotate(n1);
}
void Insert(TreeNode*& node, int data)
{
if (node == NULL)
{
TreeNode* tmp = (TreeNode*)malloc(sizeof(TreeNode));
tmp->data = data;
tmp->height = 0;
tmp->leftC = NULL;
tmp->rightC = NULL;
node = tmp;
return;
}
if (node->data > data)//结点的值大于data
{
Insert(node->leftC, data);//不断插入
if ((getHeight(node->leftC) - getHeight(node->rightC)) == 2)
{//说明需要左旋
if (data < node->leftC->data)
{
leftRotate(node);
}
else
{
DoubleRotateLR(node);
}
}
else if (node->data < data)//没有相同的值
{
Insert(node->rightC, data);
//如果高度之差为2的话就失去了平衡,需要旋转
if (2 == getHeight(node->rightC) - getHeight(node->leftC))
{
if (data > node->rightC->data)
{
rightRotate(node);
}
else
{
DoubleRotateRL(node);
}
}
}
}
node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1;
}
void preOrder(TreeNode* node)
{
if (node == NULL)
{
return;
}
cout << node->data << endl;
preOrder(node->leftC);
preOrder(node->rightC);
}
void inOrderTraversal(TreeNode* root)//非递归中序遍历
{//先左,再中,最后右,对于每个子树也是一样的顺序
stack<TreeNode *> S;
while (true)
{
if (root)
{
S.push(root);
root = root->leftC;
}
else
{
if (S.empty())
{
break;
}
root = S.top();
cout << root->data << " ";
S.pop();
root = root->rightC;
}
}
}
void deleteNode(TreeNode* &node, int x)
{
if (node == NULL) return; //没有找到值是x的节点
if (x < node->data)
{
//如果x小于节点的值,就继续在节点的左子树中删除x
deleteNode(node->leftC, x);
if (2 == getHeight(node->rightC) - getHeight(node->leftC))
{
if (node->rightC->leftC && getHeight(node->rightC->leftC) > getHeight(node->rightC->rightC))
DoubleRotateRL(node);
else
rightRotate(node);
}
}
else if (x > node->data)
{
//如果x大于节点的值,就继续在节点的右子树中删除x
deleteNode(node->rightC, x);
if (2 == getHeight(node->leftC) > getHeight(node->rightC))
{
if (node->leftC ->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC))
DoubleRotateLR(node);
else
leftRotate(node);
}
}
else //如果相等,此节点就是要删除的节点
{
if (node->leftC && node->rightC) //此节点有两个儿子
{
TreeNode* ptr = node->rightC; //ptr指向节点的右儿子
while (ptr->leftC != NULL) ptr = ptr->leftC;//找到右子树中值最小的节点
//把右子树中最小节点的值赋值给本节点
node->data = ptr->data;
//删除右子树中最小值的节点
deleteNode(node->rightC, ptr->data);
if (2 == getHeight(node->leftC) - getHeight(node->rightC))
{
if (node->leftC->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC))
DoubleRotateLR(node);
else
leftRotate(node);
}
}
else
{
TreeNode* ptr = node;
//此节点有1个或0个儿子
if (node->leftC == NULL) //有右儿子或者没有儿子
node = node->rightC;
else if (node->rightC == NULL) //有左儿子
node = node->leftC;
delete ptr;
ptr = NULL;
}
}
if (node)
node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1;
}
int main()
{
TreeNode *head;
InitTree(&head);
for (int i = 5; i > 0; --i)
{
Insert((*head).leftC, i);
}
preOrder((*head).leftC);
inOrderTraversal((*head).leftC);
cout << endl;
deleteNode((*head).leftC, 1);
inOrderTraversal((*head).leftC);
cout << endl;
Insert((*head).leftC, 1);
deleteNode((*head).leftC, 4);
inOrderTraversal((*head).leftC);
cout << endl;
preOrder((*head).leftC);
return 0;
}