文章目录
备注:实现语言为C#(.NET Core),语法和Java别无二致
综述
AVL树是二叉搜索树(Binary Search Tree)的升级版,主要就是为了解决BST在插入有序序列时会退化成链表、使查找性能由
O
(
l
o
g
n
)
O(logn)
O(logn) 变为
O
(
n
)
O(n)
O(n) 的极端情况
其用法与BST一致,都包含:
- Add()结点添加方法
- Del()结点删除方法
- Have()结点查找方法
- Previous_travel()先序遍历方法
- Medium_travel()中序遍历方法
- Post_travel()后序遍历方法
AVL树与BST的最大区别就是AVL是自平衡的。当AVL树的左右子树高度差超过ALLOWED_IMBALANCE(默认为1)时,会进行一系列的结点旋转操作来调节自身的平衡。此操作由balance()函数来实现
话不多说,上代码 ~
第一步 构建结点类
private class AVLNode // AVL树的结点类
{
public int data;
public AVLNode left;
public AVLNode right;
public int height; // 比BST多了height字段,用于记录自身高度
public AVLNode(int val)
{
this.data = val;
this.right = null;
this.left = null;
height = 0;
}
}
第二步 实现结点添加方法(重点)
// 添加方法的外部API
public void Add(int val)
{
root = Add(val, root);
size++;
}
// 递归实现部分
private AVLNode Add(int val, AVLNode node)
{
if (node == null) return new AVLNode(val);
if (val < node.data) node.left = Add(val, node.left);
else if (val > node.data) node.right = Add(val, node.right);
return balance(node); // 返回左右子树平衡的结点
}
第三步 实现结点删除方法(重难点)
// 外部API
public void Del(int val)
{
root = Del(val, root);
size--;
}
// 递归实现部分
private AVLNode Del(int val, AVLNode node)
{
if (node == null) return null;
if (val < node.data) node.left = Del(val, node.left);
else if (val > node.data) node.right = Del(val, node.right);
else // 找到要删除的结点
{
if(node.left == null)
{
if (node.right == null) return null; // 叶子结点直接删
else node = node.right; // 右子树不为空则让右子树替代自身
}
else
{
if (node.right == null) node = node.left; // 左子树不为空则让左子树替代自身
else
{ // 左右子树都不空则在右子树中找最小(或左子树中找最大也一样)的结点替代自身
AVLNode findMin = node.right;
while (findMin.left != null)
findMin = findMin.left;
node.data = findMin.data;
node.right = Del(node.data, node.right);
}
}
}
return balance(node); // 返回左右子树平衡的结点
}
第四步 实现结点的查找方法
// Have方法较为简单,所以使用while循环实现
public bool Have(int val)
{
AVLNode node = root;
while(node != null)
{
if (val < node.data)
node = node.left;
else if (val > node.data)
node = node.right;
else
return true;
}
return false;
}
第五步 实现平衡二叉树的遍历算法(先、中、后、层次)
//先序遍历
public void Previous_travel()
{
Previous_travel(root);
}
private void Previous_travel(AVLNode node)
{
if (node != null)
{
Console.Write(node.data + " ");
Previous_travel(node.left);
Previous_travel(node.right);
}
}
//中序遍历
public void Medium_travel()
{
Medium_travel(root);
}
private void Medium_travel(AVLNode node)
{
if (node != null)
{
Medium_travel(node.left);
Console.Write(node.data + " ");
Medium_travel(node.right);
}
}
//后序遍历
public void Post_travel()
{
Post_travel(root);
}
private void Post_travel(AVLNode node)
{
if (node != null)
{
Post_travel(node.left);
Post_travel(node.right);
Console.Write(node.data + " ");
}
}
//层次遍历
public void layer_travel()
{
Queue<AVLNode> nodes = new Queue<AVLNode>();
nodes.Enqueue(root);
AVLNode node = null;
while (nodes.Count != 0)
{
node = nodes.Dequeue();
if (node != null)
{
Console.Write(node.data + " ");
if (node.left != null)
nodes.Enqueue(node.left);
if (node.right != null)
nodes.Enqueue(node.right);
}
}
}
第六步 AVL树平衡算法的实现(重难点)
备注:此处很难理解,需要掌握递归程序设计思想,啃不动的要补补课了。。
//计算结点高度
private int height(AVLNode node)
{
return node == null ? -1 : node.height;
}
private const int ALLOWED_IMBALLANCE = 1; //允许最大不平衡的程度
//结点平衡方法
private AVLNode balance(AVLNode node)
{
if (node == null) return null;
if (height(node.left) - height(node.right) > ALLOWED_IMBALLANCE)
{
if (height(node.left.left) >= height(node.left.right)) // 左单旋
node = rotateLeft(node);
else // 左双旋
node = doubleRotateLeft(node);
}
else if (height(node.right) - height(node.left) > ALLOWED_IMBALLANCE)
{
if (height(node.right.right) >= height(node.right.left)) // 右单旋
node = rotateRight(node);
else // 右双旋
node = doubleRotateRight(node);
}
node.height = Math.Max(height(node.left), height(node.right)) + 1; // 更新高度
return node;
}
// 左单旋算法实现
private AVLNode rotateLeft(AVLNode node)
{
AVLNode l = node.left;
node.left = l.right;
l.right = node;
// 更新高度
node.height = Math.Max(height(node.left), height(node.right)) + 1;
l.height = Math.Max(height(l.left), node.height) + 1;
return l;
}
// 左双旋算法实现
private AVLNode doubleRotateLeft(AVLNode node)
{
node.left = rotateRight(node.left);
return rotateLeft(node);
}
// 右单旋算法实现
private AVLNode rotateRight(AVLNode node)
{
AVLNode r = node.right;
node.right = r.left;
r.left = node;
// 更新高度
node.height = Math.Max(height(node.left), height(node.right)) + 1;
r.height = Math.Max(height(r.right), node.height) + 1;
return r;
}
// 右双旋算法实现
private AVLNode doubleRotateRight(AVLNode node)
{
node.right = rotateLeft(node.right);
return rotateRight(node);
}
完整代码实现
class AVLTree
{
private class AVLNode
{
public int data;
public AVLNode left;
public AVLNode right;
public int height;
public AVLNode(int val)
{
this.data = val;
this.right = null;
this.left = null;
height = 0;
}
public AVLNode(int val, AVLNode r, AVLNode l)
{
this.data = val;
this.right = r;
this.left = l;
height = 0;
}
}
private int size;
public int Size
{
get
{
return size;
}
}
private AVLNode root;
public AVLTree()
{
size = 0;
root = null;
}
public void Add(int val)
{
root = Add(val, root);
size++;
}
public void Del(int val)
{
root = Del(val, root);
size--;
}
public bool Have(int val)
{
AVLNode node = root;
while(node != null)
{
if (val < node.data)
node = node.left;
else if (val > node.data)
node = node.right;
else
return true;
}
return false;
}
//先序遍历
public void Previous_travel()
{
Previous_travel(root);
}
private void Previous_travel(AVLNode node)
{
if (node != null)
{
Console.Write(node.data + " ");
Previous_travel(node.left);
Previous_travel(node.right);
}
}
//中序遍历
public void Medium_travel()
{
Medium_travel(root);
}
private void Medium_travel(AVLNode node)
{
if (node != null)
{
Medium_travel(node.left);
Console.Write(node.data + " ");
Medium_travel(node.right);
}
}
//后序遍历
public void Post_travel()
{
Post_travel(root);
}
private void Post_travel(AVLNode node)
{
if (node != null)
{
Post_travel(node.left);
Post_travel(node.right);
Console.Write(node.data + " ");
}
}
//层次遍历
public void layer_travel()
{
Queue<AVLNode> nodes = new Queue<AVLNode>();
nodes.Enqueue(root);
AVLNode node = null;
while (nodes.Count != 0)
{
node = nodes.Dequeue();
if (node != null)
{
Console.Write(node.data + " ");
if (node.left != null)
nodes.Enqueue(node.left);
if (node.right != null)
nodes.Enqueue(node.right);
}
}
}
private int height(AVLNode node)
{
return node == null ? -1 : node.height;
}
private AVLNode Add(int val, AVLNode node)
{
if (node == null) return new AVLNode(val);
if (val < node.data) node.left = Add(val, node.left);
else if (val > node.data) node.right = Add(val, node.right);
else {}
return balance(node);
}
private AVLNode Del(int val, AVLNode node)
{
if (node == null) return null;
if (val < node.data) node.left = Del(val, node.left);
else if (val > node.data) node.right = Del(val, node.right);
else
{
if(node.left == null)
{
if (node.right == null) return null;
else node = node.right;
}
else
{
if (node.right == null) node = node.left;
else
{
AVLNode findMin = node.right;
while (findMin.left != null)
findMin = findMin.left;
node.data = findMin.data;
node.right = Del(node.data, node.right);
}
}
}
return balance(node);
}
//结点平衡方法
private const int ALLOWED_IMBALLANCE = 1; //允许最大不平衡的程度
private AVLNode balance(AVLNode node)
{
if (node == null) return null;
if (height(node.left) - height(node.right) > ALLOWED_IMBALLANCE)
{
if (height(node.left.left) >= height(node.left.right)) // 左单旋
node = rotateLeft(node);
else // 左双旋
node = doubleRotateLeft(node);
}
else if (height(node.right) - height(node.left) > ALLOWED_IMBALLANCE)
{
if (height(node.right.right) >= height(node.right.left)) // 右单旋
node = rotateRight(node);
else // 右双旋
node = doubleRotateRight(node);
}
else {}
node.height = Math.Max(height(node.left), height(node.right)) + 1; // 更新高度
return node;
}
// 左单旋算法实现
private AVLNode rotateLeft(AVLNode node)
{
AVLNode l = node.left;
node.left = l.right;
l.right = node;
// 更新高度
node.height = Math.Max(height(node.left), height(node.right)) + 1;
l.height = Math.Max(height(l.left), node.height) + 1;
return l;
}
// 左双旋算法实现
private AVLNode doubleRotateLeft(AVLNode node)
{
node.left = rotateRight(node.left);
return rotateLeft(node);
}
// 右单旋算法实现
private AVLNode rotateRight(AVLNode node)
{
AVLNode r = node.right;
node.right = r.left;
r.left = node;
// 更新高度
node.height = Math.Max(height(node.left), height(node.right)) + 1;
r.height = Math.Max(height(r.right), node.height) + 1;
return r;
}
// 右双旋算法实现
private AVLNode doubleRotateRight(AVLNode node)
{
node.right = rotateLeft(node.right);
return rotateRight(node);
}
}
调试代码及运行结果
class Program
{
static void Main(string[] args)
{
string[] nums = Console.ReadLine().Split(" ");
AVLTree tree = new AVLTree();
foreach (string num in nums)
tree.Add(int.Parse(num));
Console.WriteLine("树中元素的个数为:{0}", tree.Size);
if (tree.Have(2))
Console.WriteLine("树中包含2这个元素");
else
Console.WriteLine("树中不包含2这个元素");
Console.Write("先序遍历结果:");
tree.Previous_travel();
Console.Write("\n中序遍历结果:");
tree.Medium_travel();
Console.Write("\n后序遍历结果:");
tree.Post_travel();
Console.Write("\n层序遍历结果:");
tree.layer_travel();
Console.Write("\n请输入要删除的元素:");
int del = int.Parse(Console.ReadLine());
tree.Del(del);
Console.Write("删除后先序遍历结果:");
tree.Previous_travel();
Console.Write("\n删除后中序遍历结果:");
tree.Medium_travel();
Console.Write("\n删除后后序遍历结果:");
tree.Post_travel();
Console.Write("\n删除后层序遍历结果:");
tree.layer_travel();
Console.ReadKey();
}
}
运行结果:
平衡方法参考自https://blog.youkuaiyun.com/weixin_41186657/article/details/84109017