1 题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
2 思路和方法
平衡二叉树,又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。https://blog.csdn.net/qq_43091156/article/details/88558966
从叶节点开始,依次往上求其子树高度,如果在某一子树上不满足要求,则一路返回,不再继续遍历。即,先依次遍历左子树,如果左子树是平衡二叉树,再依次遍历右子树。时间最坏O(n),空间O(n)。
3 C++核心代码

1 class Solution {
2 public:
3 // 返回值:树的深度
4 bool IsBalanced_Solution(TreeNode* pRoot){
5 if (pRoot == nullptr)
6 return true; // ko
7 return TreeDepth(pRoot)!=-1;
8 }
9
10 // 返回值:
11 // -1:子树不平衡
12 // >0:子树深度
13 int TreeDepth(TreeNode* pRoot){
14 if (pRoot == nullptr)
15 return 0;
16
17 int left = TreeDepth(pRoot->left);
18 if(left==-1) //若左子树不满足平衡,则整个树已不是平衡二叉树了,直接返回,不处理右子树
19 return -1;
20 int right = TreeDepth(pRoot->right);
21 if(right ==-1)
22 return -1;
23 if(left-right > 1 || left - right <-1)
24 return -1;
25 return left>right ? left+1:right+1;
26 }
27 };
4 AVL平衡二叉树的代码

1 #include <iostream>
2 #include <algorithm>
3
4 using namespace std;
5
6 class AVLNode{
7 public:
8 int data;
9 int height;//结点的高度,叶子结点高度为1
10 AVLNode* lChild;
11 AVLNode* rChild;
12 public:
13 AVLNode(int data) :data(data), height(1), lChild(0), rChild(0){}
14 };
15
16 class AVL{
17 public:
18 AVLNode* root;
19 public:
20 AVL(){
21 root = nullptr;
22 }
23 ~AVL(){
24 delete root;
25 }
26 int height(AVLNode* root){
27 if (root){
28 return root->height;
29 }
30 return 0;
31 }
32 //找到树中最大结点并将其返回
33 AVLNode* finMaxNode(AVLNode* root){
34 //一直往右找
35 if (root->rChild){
36 root = root->rChild;
37 }
38 return root;
39 }
40 //找到树中最小结点并将其返回
41 AVLNode* finMinNode(AVLNode* root){
42 //一直往左找
43 if (root->lChild){
44 root = root->lChild;
45 }
46 return root;
47 }
48 //以p为根结点右旋转,返回新的根结点
49 AVLNode* llRotate(AVLNode* p){
50 AVLNode* pleft = p->lChild;
51 p->lChild = pleft->rChild;
52 pleft->rChild = p;
53 //结点的高度由该节点的子树唯一决定,所以只有子树发生变化的结点才需要更新高度值
54 pleft->height = max(height(pleft->lChild), height(pleft->rChild)) + 1;
55 p->height = max(height(p->lChild), height(p->rChild)) + 1;
56 return pleft;
57 }
58 //左旋转
59 AVLNode* rrRotate(AVLNode* p){
60 AVLNode* pright = p->rChild;
61 p->rChild = pright->lChild;
62 pright->lChild = p;
63 pright->height = max(height(pright->lChild), height(pright->rChild)) + 1;
64 p->height = max(height(p->lChild), height(p->rChild)) + 1;
65 return pright;
66 }
67 //先左,再右
68 AVLNode* lrRotate(AVLNode* p){
69 AVLNode* pleft = rrRotate(p->lChild);
70 return llRotate(p);
71 }
72 //先右,再左
73 AVLNode* rlRotate(AVLNode* p){
74 AVLNode* pright = llRotate(p->rChild);
75 return rrRotate(p);
76 }
77 //插入新结点,保持平衡
78 void insert(int data, AVLNode*& root){
79 if (!root){
80 root = new AVLNode(data);
81 }
82 else{
83 if (data < root->data){
84 insert(data, root->lChild);
85 //插入新结点后,如果打破平衡,则需要动态调整
86 if (height(root->lChild) - height(root->rChild) == 2){
87 if (data < root->lChild->data)
88 root = llRotate(root);
89 else
90 root = lrRotate(root);
91 }
92 }
93 else if (data > root->data){
94 insert(data, root->rChild);
95 //插入新结点后,如果打破平衡,则需要动态调整
96 if (height(root->rChild) - height(root->lChild) == 2){
97 if (data > root->rChild->data)
98 root = rrRotate(root);
99 else
100 root = rlRotate(root);
101 }
102 }
103 else{
104 cout << "AVL中已存在该值:" << data << endl;
105 }
106 }
107 //平衡后,需要更新根结点的高度值
108 root->height = max(height(root->lChild), height(root->rChild)) + 1;
109 }
110 //删除结点,保持平衡
111 void del(int data, AVLNode*& root){
112 if (data < root->data){
113 del(data, root->lChild);
114 //删除点之后,若AVL树失去平衡,则进行调整
115 if (height(root->rChild) - height(root->lChild) == 2){
116 AVLNode* r = root->rChild;
117 if (height(r->lChild) > height(r->rChild))
118 root = rlRotate(root);
119 else
120 root = rrRotate(root);
121 }
122 }
123 else if (data > root->data){
124 del(data, root->rChild);
125 //删除点之后,若AVL树失去平衡,则进行调整
126 if (height(root->lChild) - height(root->rChild) == 2){
127 AVLNode* l = root->lChild;
128 if (height(l->lChild) > height(l->rChild))
129 root = llRotate(root);
130 else
131 root = lrRotate(root);
132 }
133 }
134 else{
135 //此时root为要删除的点
136 if (root->lChild && root->rChild){
137 if (height(root->lChild) > height(root->rChild)){
138 // 如果root的左子树比右子树高;
139 // 则(01)找出root的左子树中的最大节点
140 // (02)将该最大节点的值赋值给root。
141 // (03)删除该最大节点。
142 // 这类似于用"root的左子树中最大节点"做"root"的替身;
143 // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
144 AVLNode* maxNode = finMaxNode(root->lChild);
145 root->data = maxNode->data;
146 del(maxNode->data, root->lChild);
147 }
148 else{
149 AVLNode* minNode = finMinNode(root->rChild);
150 root->data = minNode->data;
151 del(minNode->data, root->rChild);
152 }
153 }
154 else{
155 if (root->lChild){
156 root->data = root->lChild->data;
157 root->lChild = nullptr;
158 }
159 else if (root->rChild){
160 root->data = root->rChild->data;
161 root->rChild = nullptr;
162 }
163 else{
164 root = nullptr;//参数是引用,所以此处修改了主函数中的root值
165 }
166 }
167 }
168 }
169 void inOrder(AVLNode* root){
170 if (root){
171 inOrder(root->lChild);
172 cout << root->data << endl;
173 inOrder(root->rChild);
174 }
175 }
176 };
177
178 int main(){
179 AVL tree;
180 tree.insert(5, tree.root);
181 tree.insert(15, tree.root);
182 tree.insert(25, tree.root);
183 tree.insert(35, tree.root);
184 tree.insert(45, tree.root);
185 tree.insert(55, tree.root);
186 tree.del(55, tree.root);
187 tree.inOrder(tree.root);
188
189 system("pause");
190 return 0;
191 }
参考资料
https://blog.csdn.net/qq_39559641/article/details/83720734(代码很详细全面,写的很好,知识点讲解详细)
https://blog.csdn.net/zjwreal/article/details/88833908
https://blog.csdn.net/qq_43091156/article/details/88558966
https://blog.csdn.net/vaemusicsky/article/details/81607251(AVL平衡二叉树的代码)
