AVL树与实现

目录

简介

算法时间复杂度

AVL树上的操作

什么情况下使用AVL树?

AVL 旋转操作

代码实现(python,C++,C)


简介

AVL 树由 GM Adelson - Velsky EM Landis 1962 年发明。该树被命名为 AVL,以纪念其发明者。AVL 树定义为高度平衡的二叉搜索树,其中每个节点都与一个平衡因子相关联,该平衡因子是通过从其左子树的高度减去其右子树的高度来计算的。

平衡系数(BF= 左子树高度右子树高度

如果每个节点的平衡因子在-11之间,则称树是平衡的,否则,树将不平衡,需要重新调整到平衡。

如果任一节点的平衡因子为1,则表示左子树比右子树高一级。

如果任一节点的平衡因子为0,则表示左子树和右子树的高度相等。

如果任一节点的平衡因子为-1,则表示左子树比右子树低一级。

下图给出了 AVL 树。我们可以看到,与每个节点相关的平衡因子在 -1 +1 之间。因此,它是 AVL 树平衡树的一个示例。

平衡的AVL树

算法时间复杂度

算法    平均情况     最差的情况

空间    O(n)             O(n)

搜索    O(log n)       O(log n)

插入    O(log n)       O(log n)

删除    O(log n)       O(log n)

AVL树上的操作

由于 AVL 树也是二叉搜索树,因此所有操作的执行方式与在二叉搜索树中执行的方式相同。搜索和遍历不会导致违反 AVL 树的属性。但是,插入和删除是可能违反此属性的操作,因此需要重新调整树。

什么情况下使用AVL树?

AVL 树通过旋转操作来控制二叉搜索树(BST)的高度。高度为 h 的二叉搜索树中所有操作所需的时间为O(h)。但是,如果 BST 树变得倾斜(即最坏情况),它的操作时间则退化到O(n)AVL通过限制BST高度为 log n,控制每种操作的时间上限为O(log n),其中 n 是节点数。在查询操作更为频繁的情况下使用AVL树,如果插入和删除操作比较频繁的情况下,建议使用红黑树。

 倾斜的二叉搜索树(BST)和单链表结构一致

AVL 旋转操作

只有在平衡因子(Balance Factor 不是-10 1的情况下,我们才会在 AVL 树中执行旋转。

基本上有四种类型的旋转,如下所示:

RR型旋转:插入的节点在A的左子树的左子树中,RR型旋转是逆时针旋转

RR型旋转

LL型旋转:插入的节点在 A 的右子树的右子树中,LL型旋转是顺时针旋转

LL型旋转

LR型旋转:插入的节点在A的左子树的右子树中

LR型旋转

RL旋转:插入的节点在 A 的右子树的左子树中

RL型旋转

其中节点 A 平衡因子不是 -1, 0, 1 的节点,红色的C为插入节点。

前两个旋转 LL RR 是单旋转,接下来的两个旋转 LR RL 是双旋转。对于平衡树,最小高度必须至少为 2

下面来看稍微复制的一点的LRRL旋转

1. LR型旋转

LR型旋转

在4节点左子树插入3节点时,5节点的BF=2,因此,5节点成为不平衡节点。3节点插入在5节点的左子树的右子树中,这种情况是 LR 型旋转,LR = RR + LL,因此首先执行以2节点为根的子树上的 RR型旋转,3节点成为2节点的右子树,在执行以5节点为根的 LL型旋转。现在每个节点的平衡因子要么是-1,要么是0,要么是1,即BST现在是平衡的。

2. RL型旋转

RL旋转

RL = LL + RR,上图中2节点为不平衡节点,4节点插入在2节点的右子树的左子树中,这种情况是 RL 型旋转,因此先执行以2节点的右子树的根节点(5节点)的LL型旋转,4节点变成5节点的左节点,在执行以2节点为根节点的RR型旋转。现在每个节点的平衡因子要么是-1,要么是0,要么是1,即BST树现在是平衡的。

代码实现(python,C++,C)

# python

from functools import reduce
import numpy as np
        
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
        self.height = 1
        
    def __str__(self):
        return f"{self.val}"
 
class AVL_Tree:
    def __init__(self):
        self.root = None
        self.distance = 2
        self.log = []
 
    def insert(self, key):
        self.root = self._insert(self.root, key)
        
    def _insert(self, root, key):
        if not root:
            return TreeNode(key)
        elif key < root.val:
            root.left = self._insert(root.left, key)
        else:
            root.right = self._insert(root.right, key)
 
        root.height = 1 + max(self._getHeight(root.left),
                           self._getHeight(root.right))
 
        balance = self._getBalance(root)
 
        # LL旋转
        if balance > 1 and key < root.left.val:
            return self._rightRotate(root)
 
        # RR旋转
        if balance < -1 and key > root.right.val:
            return self._leftRotate(root)
 
        # LR旋转
        if balance > 1 and key > root.left.val:
            root.left = self._leftRotate(root.left)
            return self._rightRotate(root)
 
        # RL旋转
        if balance < -1 and key < root.right.val:
            root.right = self._rightRotate(root.right)
            return self._leftRotate(root)
 
        return root
    
    def delete(self, key):
        self._delete(self.root, key)
        
    def _delete(self, root, key):
        if not root:
            return root
        elif key < root.val:
            root.left = self._delete(root.left, key)
        elif key > root.val:
            root.right = self._delete(root.right, key)
        else:
            if root.left is None:
                temp = root.right
                root = None
                return temp
 
            elif root.right is None:
                temp = root.left
                root = None
                return temp
 
            temp = self._getMinNode(root.right)
            root.val = temp.val
            root.right = self._delete(root.right, temp.val)
 
        if root is None:
            return root
 
        root.height = 1 + max(self._getHeight(root.left),
                            self._getHeight(root.right))
 
        balance = self._getBalance(root)
 
        # LL旋转
        if balance > 1 and self._getBalance(root.left) >= 0:
            return self._rightRotate(root)
 
        # RR旋转
        if balance < -1 and self._getBalance(root.right) <= 0:
            return self._leftRotate(root)
 
        # LR旋转
        if balance > 1 and self._getBalance(root.left) < 0:
            root.left = self._leftRotate(root.left)
            return self._rightRotate(root)
 
        # RL旋转
        if balance < -1 and self._getBalance(root.right) > 0:
            root.right = self._rightRotate(root.right)
            return self._leftRotate(root)
 
        return root
        
    def query(self, key):
        return self._query(self.root, key)
    
    def _query(self, root, key):
        if root is None:
            return None
            
        if key == root.val:
            return root
        elif key < root.val:
            return self._query(root.left, key)
        else:
            return self._query(root.right, key)
            
    def _leftRotate(self, root):
        new_root = root.right
        T = new_root.left
 
        new_root.left = root
        root.right = T
 
        root.height = 1 + max(self._getHeight(root.left),
                         self._getHeight(root.right))
        new_root.height = 1 + max(self._getHeight(new_root.left),
                         self._getHeight(new_root.right))
 
        return new_root
 
    def _rightRotate(self, root):
        new_root = root.left
        T = new_root.right
 
        new_root.right = root
        root.left = T
 
        root.height = 1 + max(self._getHeight(root.left),
                        self._getHeight(root.right))
        new_root.height = 1 + max(self._getHeight(new_root.left),
                        self._getHeight(new_root.right))
 
        return new_root
 
    def _getMinNode(self, root):
        if root is None or root.left is None:
            return root
        return self._getMinNode(root.left)
            
    def _getHeight(self, root):
        if not root:
            return 0
 
        return root.height
 
    def _getBalance(self, root):
        if not root:
            return 0
 
        return self._getHeight(root.left) - self._getHeight(root.right)
 
    def _preOrder(self, root):
        if not root:
            return
        
        print(f'{root.val} ', end='')
        self._preOrder(root.left)
        self._preOrder(root.right)
    
    def preOrder(self):
        self._preOrder(self.root)
            
    def _print(self, node, space):
        if (node == None) :
            return
     
        space += self.distance
     
        self._print(node.right, space)
        tmp = [' ' for i in range(space - self.distance)]
        tmp.append(str(node.val))
        self.log.append(tmp)
        self._print(node.left, space)
     
    def print(self):
        self._print(self.root, 0)
        max_len = reduce(max, [len(l) for l in self.log])
        for i, log in enumerate(self.log):
            l = len(log)
            if l < max_len:
                self.log[i] += ' '*(max_len - l)
            self.log[i] = [c for c in self.log[i]]
            
        logs = np.array(self.log).T
        for log in logs:
            print(''.join(log[::-1]))
        self.log = []
        
avl_tree = AVL_Tree()

#for i in range(10):
#    avl_tree.insert(i)

avl_tree.insert(5)
avl_tree.insert(6)
avl_tree.insert(2)
avl_tree.insert(1)
avl_tree.insert(4)
avl_tree.insert(3)

avl_tree.print()


avl_tree.delete(4)
avl_tree.print()

node = avl_tree.query(2)
if node:
    print(f"query successed, value {node.val}")
 
// C++

#include <iostream>
using namespace std;

class TreeNode
{
    public:
        TreeNode(int key)
        {
            val = key;
            left = NULL;
            right = NULL;
            height = 1;
        }
        
    public:
        int val;
        TreeNode *left;
        TreeNode *right;
        int height;
};
 
class AVL_Tree
{
    public:
        AVL_Tree()
        {
            root = NULL;
            distance = 4;
        }
     
        void insert(int key)
        {
            root = _insert(root, key);
        }
        
		TreeNode *query(int key)
		{
			return _query(this->root, key);
		}
		
		void del(int key)
		{
			_delete(root, key);
		}
		
        void preOrder(void)
        {
            _preOrder(root);
        }
        
        void print(void)
        {
            _print(root, 0);
        }
        
    private:            
        TreeNode *_insert(TreeNode * root, int key)
        {
            if (!root) 
                return new TreeNode(key);
            else if (key < root->val)
                root->left = _insert(root->left, key);
            else
                root->right = _insert(root->right, key);
     
            root->height = 1 + max(_getHeight(root->left),
                               _getHeight(root->right));
     
            int balance = _getBalance(root);
     
            // LL旋转
            if (balance > 1 && key < root->left->val)
                return _rightRotate(root);
     
            // RR旋转
            if (balance < -1 && key > root->right->val)
                return _leftRotate(root);
     
            // LR旋转
            if (balance > 1 && key > root->left->val) {
                root->left = _leftRotate(root->left);
                return _rightRotate(root);
            }
     
            // RL旋转
            if (balance < -1 && key < root->right->val) {
                root->right = _rightRotate(root->right);
                return _leftRotate(root);
            }
     
            return root;
        }
        
		TreeNode *_delete(TreeNode *root, int key)
		{
			if (!root)
				return root;
			else if (key < root->val)
				root->left = _delete(root->left, key);
			else if (key > root->val)
				root->right = _delete(root->right, key);
			else {
				TreeNode *temp;
				
				if (!root->left) {
					temp = root->right;
					root = NULL;
					return temp;
				} else if (!root->right) {
					temp = root->left;
					root = NULL;
					return temp;
				} else {
					temp = _getMinNode(root->right);
					root->val = temp->val;
					root->right = _delete(root->right, temp->val);
				}
			}

			if (!root)
				return root;

			root->height = 1 + max(_getHeight(root->left),
								_getHeight(root->right));

			int balance = _getBalance(root);

			// LL旋转
			if (balance > 1 && _getBalance(root->left) >= 0)
				return _rightRotate(root);

			// RR旋转
			if (balance < -1 && _getBalance(root->right) <= 0)
				return _leftRotate(root);

			// LR旋转
			if (balance > 1 && _getBalance(root->left) < 0) {
				root->left = _leftRotate(root->left);
				return _rightRotate(root);
			}

			// RL旋转
			if (balance < -1 && _getBalance(root->right) > 0) {
				root->right = _rightRotate(root->right);
				return _leftRotate(root);
			}

			return root;
		}
		
		TreeNode *_query(TreeNode *root, int key)
		{
			if (!root)
				return NULL;
				
			if (key == root->val)
				return root;
			else if (key < root->val)
				return _query(root->left, key);
			else
				return _query(root->right, key);
		}
     
        TreeNode *_leftRotate(TreeNode * root)
        {
            TreeNode *new_root = root->right;
            TreeNode *T = new_root->left;
     
            new_root->left = root;
            root->right = T;
     
            root->height = 1 + max(_getHeight(root->left),
                             _getHeight(root->right));
            new_root->height = 1 + max(_getHeight(new_root->left),
                             _getHeight(new_root->right));
     
            return new_root;
        }
     
        TreeNode *_rightRotate(TreeNode * root)
        {
            TreeNode *new_root = root->left;
            TreeNode *T = new_root->right;
     
            new_root->right = root;
            root->left = T;
     
            root->height = 1 + max(_getHeight(root->left),
                            _getHeight(root->right));
            new_root->height = 1 + max(_getHeight(new_root->left),
                            _getHeight(new_root->right));
     
            return new_root;
        }
        
        int max(int a, int b)
        {
            return (a > b)?a:b;
        }
     
		TreeNode *_getMinNode(TreeNode *root)
		{
			if (!root || !root->left)
				return root;
			return _getMinNode(root->left);
		}
		
        int _getHeight(TreeNode *root)
        {
            if (!root)
                return 0;
     
            return root->height;
        }
     
        int _getBalance(TreeNode *root)
        {
            if (!root)
                return 0;
            
            return _getHeight(root->left) - _getHeight(root->right);
        }
        
        void _preOrder(TreeNode *root)
        {
            if (!root)
                return;
            
            cout << root->val << " ";
            _preOrder(root->left);
            _preOrder(root->right);
        }
                
        void _print(TreeNode *node, int space)
        {
            if (!node)
                return;
         
            space += distance;
         
            _print(node->right, space);

            for (int i=0; i < space - distance; i++)
                cout << " ";
            cout << node->val << endl;
         
            _print(node->left, space);
        }
        
    private:
        TreeNode *root;
        int distance;
};

int main(void)
{
    AVL_Tree avl_tree = AVL_Tree();

    avl_tree.insert(5);
    avl_tree.insert(6);
    avl_tree.insert(2);
    avl_tree.insert(1);
    avl_tree.insert(4);
    avl_tree.insert(3);
    avl_tree.print();
    
	avl_tree.del(4);
	avl_tree.print();
	
	TreeNode *node = avl_tree.query(3);
	if (node)
		cout << "query successed, value " << node->val << endl;
    return 0;
}
 
// C

#include <stdio.h>
#include <stdlib.h>

struct TreeNode
{
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    int height;
};

static const int distance = 4;

static int max(int a, int b)
{
    return (a > b)?a:b;
}

static struct TreeNode *_getMinNode(struct TreeNode *root)
{
	if (!root || !root->left)
		return root;
	return _getMinNode(root->left);
}
		
static int _getHeight(struct TreeNode *root)
{
    if (!root)
        return 0;

    return root->height;
}

static int _getBalance(struct TreeNode *root)
{
    if (!root)
        return 0;
    
    return _getHeight(root->left) - _getHeight(root->right);
}

static struct TreeNode *_leftRotate(struct TreeNode *root)
{
    struct TreeNode *new_root = root->right;
    struct TreeNode *T = new_root->left;

    new_root->left = root;
    root->right = T;

    root->height = 1 + max(_getHeight(root->left),
                     _getHeight(root->right));
    new_root->height = 1 + max(_getHeight(new_root->left),
                     _getHeight(new_root->right));

    return new_root;
}

static struct TreeNode *_rightRotate(struct TreeNode *root)
{
    struct TreeNode *new_root = root->left;
    struct TreeNode *T = new_root->right;

    new_root->right = root;
    root->left = T;

    root->height = 1 + max(_getHeight(root->left),
                    _getHeight(root->right));
    new_root->height = 1 + max(_getHeight(new_root->left),
                    _getHeight(new_root->right));

    return new_root;
}
        
static void _print_tree(struct TreeNode * node, int space)
{
    if (!node)
        return;
 
    space += distance;
 
    _print_tree(node->right, space);

    for (int i=0; i < space - distance; i++)
        printf(" ");
    printf("%d\n", node->val);
 
    _print_tree(node->left, space);
}

void print_tree(struct TreeNode * node)
{
    _print_tree(node, 0);
}

void preOrder(struct TreeNode *root)
{
    if (!root)
        return;
    
    printf("%d ", root->val);
    preOrder(root->left);
    preOrder(root->right);
}

struct TreeNode *insert(struct TreeNode *root, int key)
{
    if (!root) {
        struct TreeNode *node = (struct TreeNode *)malloc(sizeof(*root));
        node->val = key;
        node->left = NULL;
        node->right = NULL;
        node->height = 1;
        return node;
    } else if (key < root->val) {
        root->left = insert(root->left, key);
    } else {
        root->right = insert(root->right, key);
    }

    root->height = 1 + max(_getHeight(root->left),
                       _getHeight(root->right));

    int balance = _getBalance(root);

    // LL旋转
    if (balance > 1 && key < root->left->val)
        return _rightRotate(root);

    // RR旋转
    if (balance < -1 && key > root->right->val)
        return _leftRotate(root);

    // LR旋转
    if (balance > 1 && key > root->left->val) {
        root->left = _leftRotate(root->left);
        return _rightRotate(root);
    }

    // RL旋转
    if (balance < -1 && key < root->right->val) {
        root->right = _rightRotate(root->right);
        return _leftRotate(root);
    }

    return root;
}

struct TreeNode *query(struct TreeNode *root, int key)
{
	if (!root)
		return NULL;
		
	if (key == root->val)
		return root;
	else if (key < root->val)
		return query(root->left, key);
	else
		return query(root->right, key);
}

struct TreeNode *delete(struct TreeNode *root, int key)
{
	if (!root)
		return root;
	else if (key < root->val)
		root->left = delete(root->left, key);
	else if (key > root->val)
		root->right = delete(root->right, key);
	else {
		struct TreeNode *temp;
		
		if (!root->left) {
			temp = root->right;
			root = NULL;
			return temp;
		} else if (!root->right) {
			temp = root->left;
			root = NULL;
			return temp;
		} else {
			temp = _getMinNode(root->right);
			root->val = temp->val;
			root->right = delete(root->right, temp->val);
		}
	}

	if (!root)
		return root;

	root->height = 1 + max(_getHeight(root->left),
						_getHeight(root->right));

	int balance = _getBalance(root);

	// LL旋转
	if (balance > 1 && _getBalance(root->left) >= 0)
		return _rightRotate(root);

	// RR旋转
	if (balance < -1 && _getBalance(root->right) <= 0)
		return _leftRotate(root);

	// LR旋转
	if (balance > 1 && _getBalance(root->left) < 0) {
		root->left = _leftRotate(root->left);
		return _rightRotate(root);
	}

	// RL旋转
	if (balance < -1 && _getBalance(root->right) > 0) {
		root->right = _rightRotate(root->right);
		return _leftRotate(root);
	}

	return root;
}

int main(void)
{
    struct TreeNode *root;

    root = insert(root, 5);
    root = insert(root, 6);
    root = insert(root, 2);
    root = insert(root, 1);
    root = insert(root, 4);
    root = insert(root, 3);
    print_tree(root);
    
	root = delete(root, 4);
	print_tree(root);
	
	struct TreeNode *node = query(root, 3);
	if (node)
		printf("query successed, value %d\n", node->val);
    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值