此算法改编自邓俊辉教授的《数据结构(C++语言版)》一书,原算法可参见原书或这篇博客:https://blog.csdn.net/wddpfx/article/details/82082724
鉴于原算法基于较多功能,我们平时使用AVL树时并不需要,特地改写一遍,希望各位指正。有BUG的话请留言。
以下算法下载链接 链接: https://pan.baidu.com/s/1dcpPvfEYB2L0iDdwnnMsRQ 密码: cx61
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
struct Node
{
int data;
int height;
int level;
Node* father, *lchild, *rchild;
};
Node* creatAVLTree(vector<int> vec);
void insert(Node* &root, int);
void deleteX(Node* root, int);
Node* findNode(Node* root, int x);
Node* findPreNode(Node* root);
Node* findSucNode(Node* root);
//统一平衡算法
bool isBalance(Node* root);
Node* reBalance(Node* root);
int updateHeight(Node* root);
Node* findBadSubTree(Node*);//先序遍历寻找失衡子树
Node* getSubBadTree(Node*);//查找失衡子树的较高孩子节点
void connect34(Node* a, Node* b, Node* c, Node* T0, Node* T1, Node* T2, Node* T3);
//层次遍历输出元素
void levelTraversal(Node* root);
int main()
{
//vector<int> vec = { 0, 8, 10, 34, 88, 2, 4, 6, 1, 990, 1000, 99, 20, 19, 15, 79, 38, 666 };
vector<int> vec = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Node* root = creatAVLTree(vec);
deleteX(root, 2);
levelTraversal(root);
system("pause");
return 0;
}
Node* creatAVLTree(vector<int> vec)
{
Node* root = NULL;
for (auto a : vec)
{
insert(root, a);
//updateHeight(root);
root = reBalance(root);
}
return root;
}
void insert(Node* &root, int x)
{
if (root == NULL)//如果是根节点
{
root = new Node;
root->data = x;
root->height = 1;
root->lchild = root->rchild = root->father = NULL;
return;
}
if (root->data < x)
{
if (root->rchild == NULL)
{
Node* node = new Node;
node->data = x;
node->height = 1;
node->lchild = node->rchild = node->father = NULL;
root->rchild = node;//建立父子关系
node->father = root;
}
else insert(root->rchild, x);
}
else if (x <= root->data)
{
if (root->lchild == NULL)
{
Node* node = new Node;
node->data = x;
node->height = 1;
node->lchild = node->rchild = node->father = NULL;
root->lchild = node;//建立父子关系
node->father = root;
}
else insert(root->lchild, x);
}
}
void deleteX(Node* root, int x)
{
Node* node = findNode(root, x);//x所在的节点
if (node == NULL)
{
printf("不存在此节点!\n");
return;
}
Node* pre = findPreNode(node);//通过前驱节点来删除;
Node* suc = findSucNode(node);//通过后继节点来删除;
//Node* hot = node->father;
if (node->lchild != NULL && node->rchild != NULL)//左右孩子均存在
{
swap(node->data, pre->data);
node = pre;
}
Node* hot = node->father;
if (node->lchild == NULL && node->rchild == NULL)
{
if (hot != NULL)
{
hot->lchild == node ? hot->lchild = NULL : hot->rchild = NULL;
}
delete node;
}
else if (node->lchild == NULL)//左孩子为空
{
if (hot != NULL)
{
hot->lchild == node ? hot->lchild = node->rchild : hot->rchild = node->rchild;
}
node->rchild->father = hot;
delete node;
}
else if (node->rchild == NULL)//右孩子为空
{
if (hot != NULL)
{
hot->lchild == node ? hot->lchild = node->lchild : hot->rchild = node->lchild;
}
node->lchild->father = hot;
delete node;
}
reBalance(root);
//updateHeight(root);
}
Node* findNode(Node* root, int x)
{
if (root == NULL || root->data == x) return root;
if (root->data < x) return findNode(root->rchild, x);
else return findNode(root->lchild, x);
}
Node* findPreNode(Node* root)
{
if (root == NULL || root->lchild == NULL) return NULL;
Node* node = root->lchild;
while (node->rchild != NULL) node = node->rchild;
return node;
}
Node* findSucNode(Node* root)
{
if (root == NULL || root->rchild == NULL) return NULL;
Node* node = root->rchild;
while (node->lchild != NULL) node = node->lchild;
return node;
}
bool isBalance(Node* root)
{
if (root->lchild == NULL && root->rchild == NULL) return true;
else if (root->lchild == NULL && root->rchild != NULL)return root->rchild->height <= 1;
else if (root->lchild != NULL && root->rchild == NULL) return root->lchild->height <= 1;
else return abs(root->rchild->height - root->lchild->height) <= 1;
}
Node* reBalance(Node* root)
{
Node *x, *y, *z, *p;//p为第一个非平衡子树根节点的父节点
x = y = z = NULL;
x = findBadSubTree(root);
if (x == NULL)
{
cout << "AVL树已经平衡" << endl;
return root;
}
p = x->father;
y = getSubBadTree(x);
if (y == NULL) cout << "y出错啦!" << endl;
z = getSubBadTree(y);
if (z == NULL) cout << "z出错啦!" << endl;
Node *a, *b, *c, *T0, *T1, *T2, *T3;
if (y == x->lchild)
{
if (z == y->lchild)
{
a = z;
b = y;
c = x;
T0 = z->lchild;
T1 = z->rchild;
T2 = y->rchild;
T3 = a->rchild;
}
else
{
a = y;
b = z;
c = x;
T0 = y->lchild;
T1 = z->lchild;
T2 = z->rchild;
T3 = x->rchild;
}
}
else
{
if (z == y->rchild)
{
a = x;
b = y;
c = z;
T0 = x->lchild;
T1 = y->lchild;
T2 = z->lchild;
T3 = z->rchild;
}
else
{
a = x;
b = z;
c = y;
T0 = x->lchild;
T1 = z->lchild;
T2 = z->rchild;
T3 = y->rchild;
}
}
connect34(a, b, c, T0, T1, T2, T3);
//if(x->father == NULL)
if (p == NULL)
{
b->father = NULL;
root = b;
}
else if (x == p->lchild)
{
p->lchild = b;
b->father = p;
}
else
{
p->rchild = b;
b->father = p;
}
updateHeight(root);
return root;
}
int updateHeight(Node* root)
{
if (root->lchild == NULL && root->rchild == NULL)
{
root->height = 1;
return root->height = 1;
}
else if (root->lchild == NULL && root->rchild != NULL) root->height = updateHeight(root->rchild) + 1;
else if (root->lchild != NULL && root->rchild == NULL) root->height = updateHeight(root->lchild) + 1;
else root->height = max(updateHeight(root->lchild), updateHeight(root->rchild)) + 1;
}
Node* findBadSubTree(Node* root)
{
updateHeight(root);
if (root == NULL) return NULL;
stack<Node*> sta;
while (true)
{
if (isBalance(root) == false)
{
return root;
}
if (root->rchild != NULL) sta.push(root->rchild);
if (root->lchild != NULL) sta.push(root->lchild);
if (sta.empty()) break;
root = sta.top();
sta.pop();
}
return NULL;
}
Node* getSubBadTree(Node* root)
{
if (root->lchild != NULL && root->rchild != NULL)
{
return root->lchild->height > root->rchild->height ? root->lchild : root->rchild;
}
else if (root->lchild != NULL && root->rchild == NULL) return root->lchild;
else if (root->lchild == NULL && root->rchild != NULL) return root->rchild;
return NULL;
}
void connect34(Node* a, Node* b, Node* c, Node* T0, Node* T1, Node* T2, Node* T3)
{
b->lchild = a, a->father = b;
b->rchild = c, c->father = b;
a->lchild = T0; if (T0 != NULL) T0->father = a;
a->rchild = T1; if (T1 != NULL) T1->father = a;
c->lchild = T2; if (T2 != NULL) T2->father = c;
c->rchild = T3; if (T3 != NULL) T3->father = c;
}
//输出
void levelTraversal(Node* root)
{
queue<Node*> Q;
Q.push(root);
root->level = 1;
int nowLevel = root->level;
printf("第%d层:\n", nowLevel);
while (!Q.empty())
{
Node* front = Q.front();
Q.pop();
int level = front->level;
if (level != nowLevel)
{
nowLevel = level;
printf("\n第%d层:\n", nowLevel);
}
printf("%d height = %d\n", front->data, front->height);
if (front->lchild != NULL)
{
Q.push(front->lchild);
front->lchild->level = level + 1;
}
if (front->rchild != NULL)
{
Q.push(front->rchild);
front->rchild->level = level + 1;
}
}
printf("\n");
}