【数据结构与算法分析】第四章 树-AVL树 (三)

【数据结构与算法分析】树(三)

AVL树

介绍

AVL树是高度平衡的二叉树,它的特点是:AVL树中任何结点的两个子树的高度最大差别为1。

《【数据结构与算法分析】第四章 树-AVL树 (三)》

AVL树的查找、插入和删除操作在平均和最坏情况下都是O(logn)。

如果在AVL树中插入或删除结点后,使得高度之差大于1,此时,AVL树的平衡状态就被破坏,它就不是一颗平衡二叉树;为了让它重新维持在一个平衡状态,就需要对其进行旋转处理。学AVL树,重点的地方也就是它的旋转算法。

————————————————————————————————————————————————————————————————————————————

算法实现

树的定义

树的结点

template<class T>
class AVLTreeNode
{
    public:
        T key;    // 关键字(键值)
        int height;    // 高度
        AVLTreeNode *left;    // 左孩子
        AVLTreeNode *right;    // 右孩子
    
        AVLTreeNode(T value, AVLTreeNode *l, AVLTreeNode *r) :
            key(value) ,left(l),right(r) {}
};

树的类

template<class T>
class AVLTree
{
    private:
        AVLTreeNode<T> *root;    // 根结点
    
    public:
        // 外部接口 
         AVLTree();
         ~AVLTree();
         
        // 获取树的高度
        int height();
        // 比较两个值的大小 
        int max(int a, int b);
        
        // 前序遍历
        void preOrder();
        // 中序遍历
        void inOrder();
        // 后序遍历
        void postOrder();
        
        // (递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* search(T key);
        // (非递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* iterativeSearch(T key);
        
        // 查找最小结点:返回最小结点的键值
        T minimum();
        // 查找最大结点:返回最大结点的键值
        T maximum();
        
        // 将结点插入到AVL树中
        void insert(T key);
        // 删除结点
        void remove(T key);
        
        // 销毁AVL树
        void destroy();
        
        // 打印AVL树
        void print();
    
    private:
        // 内部接口 
        // 获取树的高度
        int height(AVLTreeNode<T> *tree);
        
        // 前序遍历
        void preOrder(AVLTreeNode<T> *tree) const;
        // 中序遍历
        void inOrder(AVLTreeNode<T> *tree) const;
        // 后序遍历
        void postOrder(AVLTreeNode<T> *tree) const;
        
        // (递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* search(AVLTreeNode<T> *x, T key) const;
        // (非递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* iterativeSearch(AVLTreeNode<T> *x, T key) const;
        
        // 返回最小结点 
        AVLTreeNode<T>* minimum(AVLTreeNode<T> *tree);
        // 返回最大结点 
        AVLTreeNode<T>* maximum(AVLTreeNode<T> *tree);
        
        // 将结点插入到AVL树中
        AVLTreeNode<T>* insert(AVLTreeNode<T>* &tree, T key);
        // 删除结点,并返回被删除的结点 
        AVLTreeNode<T>* remove(AVLTreeNode<T>* &tree, AVLTreeNode<T> *z);
        
        // 销毁AVL树
        void destroy(AVLTreeNode<T>* &tree);
        
        // 打印AVL树
        void print(AVLTreeNode<T> *tree,T key,int direction);
        
        // LL:左左对应的情况(左单旋转)
        AVLTreeNode<T>* leftLeftRotation(AVLTreeNode<T> *k2);
        // RR:右右对应的情况(右单旋转)
        AVLTreeNode<T>* rightRightRotation(AVLTreeNode<T> *k1);
        // LR:左右对应的情况(左双旋转)
        AVLTreeNode<T>* leftRightRotation(AVLTreeNode<T> *k3);
        // RL:右左对应的情况(右双旋转)
        AVLTreeNode<T>* rightLeftRotation(AVLTreeNode<T> *k1);    
};

树的高度

采用维基百科上的定义:树的高度为最大层次,即空的二叉树的高度是0,非空树的高度等于它的最大层次(根的层次为1,根的子节点为第2层,依次类推)。

template<class T>
int AVLTree<T>::height(AVLTreeNode<T> *tree)
{
	if(tree!=NULL)
		return tree->height;
	return 0;
}
 
template<class T>
int AVLTree<T>::height()
{
	return height(root);
}

旋转

如果在AVL树中进行插入或删除结点后,可能导致AVL树失去平衡。这种失去平衡可以概括为4种姿态:LL(左左)、LR(左右)、RR(右右)、和RL(右左)。

下面给出它们的示意图:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

它们各自的定义如下:

1)LL:插入或删除一个结点后,根节点的左子树的左子树还有非空结点,导致根的左子树的高度比根的右子树的高度大2,AVL树因此失去平衡。

例如,在上面LL情况中,由于根节点(8)的左子树(4)的左子树(2)还有非空子节点,而根节点(8)的右子树(12)没有子节点;导致根节点(8)的左子树(4)的高度比根节点(8)的右子树(12)高2。

2)LR:插入或删除一个结点后,根节点的左子树的右子树还有非空结点,导致根的左子树的高度比根的右子树的高度大2,AVL树因此失去平衡。

例如,在上面LR情况中,由于根节点(8)的左子树(4)的右子树(6)还有非空子节点,而根节点(8)的右子树(12)没有子节点;导致根节点(8)的左子树(4)的高度比根节点(8)的右子树(12)高2。

3)RL:插入或删除一个结点后,根节点的右子树的左子树还有非空结点,导致根的右子树的高度比根的左子树的高度大2,AVL树因此失去平衡。

例如,在上面RL情况中,由于根节点(8)的右子树(12)的左子树(10)还有非空子节点,而根节点(8)的左子树(4)没有子节点;导致根节点(8)的右子树(12)的高度比根节点(8)的左子树高2。

4)RR:插入或删除一个结点后,根节点的右子树的右子树还有非空结点,导致根的右子树的高度比根的左子树的高度大2,AVL树因此失去平衡。

例如,在上面RR情况中,由于根节点(8)的右子树(12)的右子树(14)还有非空子节点,而根节点(8)的左子树(4)没有子节点;导致根节点(8)的右子树(12)的高度比根节点(8)的左子树高2。

 

在AVL树失去平衡之后,可以通过相应的旋转使其恢复平衡,对应的旋转方法如下:

1)LL的旋转

LL失去平衡的情况,可以通过一次旋转让AVL树恢复平衡,如下图:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

可以理解为:LL旋转是围绕失去平衡的AVL根节点进行的,也就是节点k2;而且由于是LL情况,就用手抓着左孩子(即k1)使劲摇,使得k1变成根节点,k2变成k1的右子树,k1的右子树变成k2的左子树。

旋转代码:

template<class T>
AVLTreeNode<T>* AVLTree<T>::leftLeftRotation(AVLTreeNode<T> *k2)
{
	AVLTreeNode<T> *k1;
	
	k1 = k2->left;
	k2->left = k1->right;
	k1->right = k2;
	
	k2->height = max(height(k2->left), height(k2->right)) + 1;
	k1->height = max(height(k1->left), k2->height) + 1;
	
	return k1;
}

2)RR的旋转

理解了LL之后,RR就相当容易理解了。RR是LL对称的情况,示意图如下:
《【数据结构与算法分析】第四章 树-AVL树 (三)》

旋转代码:

template<class T>
AVLTreeNode<T>* AVLTree<T>::rightRightRotation(AVLTreeNode<T> *k1)
{
	AVLTreeNode<T> *k2;
	
	k2 = k1->right;
	k1->right = k2->left;
	k2->left = k1;
	
	k1->height = max(height(k1->left), height(k1->right)) + 1;
	k2->height = max(k1->height, height(k2->right)) + 1;
	
	return k2; 
}

3)LR的旋转

LR失去平衡的情况,需要经过两次旋转才能让AVL树恢复平衡,如下图所示:
《【数据结构与算法分析】第四章 树-AVL树 (三)》

第一次旋转是围绕k1进行RR旋转,第二次是围绕k3进行LL旋转。

旋转代码:

template <class T>
AVLTreeNode<T>* AVLTree<T>::leftRightRotation(AVLTreeNode<T>* k3)
{
	k3->left = rightRightRotation(k3->left);
	
	return leftLeftRotation(k3);
}

4)RL的旋转

RL是与LR对称的情况,示意图如下:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

第一次旋转是围绕k3进行的LL旋转,第二次是围绕k1进行的RR旋转。

旋转代码:

template <class T>
AVLTreeNode<T>* AVLTree<T>::rightLeftRotation(AVLTreeNode<T>* k1)
{
	k1->right = leftLeftRotation(k1->right);
	
	return rightRightRotation(k1);
}

插入

template<class T>
AVLTreeNode<T>* AVLTree<T>::insert(AVLTreeNode<T>* &tree, T key)
{
	if(tree==NULL)
	{
		// 新建结点 
		tree = new AVLTreeNode<T>(key, NULL, NULL);
		if(tree==NULL)
		{
			cout<<"ERROR: create avltree node failed!"<<endl;
			return NULL;
		}
	}
	else if(key<tree->key)
	{
		tree->left = insert(tree->left, key);
		// 插入结点后,若AVL树失去平衡,则进行相应的调节
		if(height(tree->left)-height(tree->right)==2)
		{
			if(key<tree->left->key)
				tree = leftLeftRotation(tree);
			else
				tree = leftRightRotaion(tree);
		} 
	}
	else
	{
		tree->right = insert(tree->right, key);
		// 插入结点后,若AVL树失去平衡,则进行相应的调节
		if(height(tree->right)-height(tree->left)==2)
		{
			if(key>tree->right->key)
				tree = rightRightRotation(tree);
			else
				tree = rightLeftRotaion(tree);
		} 
	}
	
	tree->height = max(height(tree->left), height(tree->right)) + 1;
	
	return tree;
}
 
template<class T>
void AVLTree<T>::insert(T key)
{
	insert(root,key);
}

删除

template<class T>
AVLTreeNode<T>* AVLTree<T>::remove(AVLTreeNode<T>* &tree, AVLTreeNode<T> *z)
{
	// 根为空 或者 没有要删除的结点
	if(tree==NULL || z==NULL)
		return NULL;
	if(z->key<tree->key)
	{
		tree->left = remove(tree->left, z);
		// 删除结点后,若AVL树失去平衡,则进行相应调节
		if(height(tree->right)-height(tree->left)==2)
		{
			AVLTreeNode<T> *r = tree->right;
			if(height(r->left)>height(r->right))
				tree = rightLeftRotation(tree);
			else
				tree = rightRightRotation(tree);
		} 
	} 
	else if(z->key>tree->key)
	{
		tree->right = remove(tree->right, z);
		if(height(tree->left)-height(tree->right)==2)
		{
			AVLTreeNode<T> *r = tree->left;
			if(height(r->left)<height(r->right))
				tree = leftRightRotation(tree);
			else
				tree = leftLeftRotation(tree);
		}
	}
	else	// tree是对应要删除的结点 
	{
		// tree的左右孩子都非空 
		if((tree->left!=NULL)&&(tree->right!=NULL))
		{
			if(height(tree->left)>height(tree->right))
			{
				// 如果tree的左子树比右子树高;
                // 则(01)找出tree的左子树中的最大节点
                //   (02)将该最大节点的值赋值给tree。
                //   (03)删除该最大节点。
                // 这类似于用"tree的左子树中最大节点"做"tree"的替身;
                // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
                AVLTreeNode<T> *max = maximum(tree->left);
                tree->key = max->key;
                tree->left = remove(tree->left, max);
			}
			else
			{
				// 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
                // 则(01)找出tree的右子树中的最小节点
                //   (02)将该最小节点的值赋值给tree。
                //   (03)删除该最小节点。
                // 这类似于用"tree的右子树中最小节点"做"tree"的替身;
                // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
                AVLTreeNode<T> *min = minimum(tree->right);
                tree->key = min->key;
				tree->right = remove(tree->right, min); 
			}
		}
		else
		{
			AVLTreeNode<T> *tmp = tree;
			tree = (tree->left!=NULL) ? tree->left : tree->right;
			delete tmp;
		}
	}
	
	return tree;
}
 
template<class T>
void AVLTree<T>::remove(T key)
{
    AVLTreeNode<T> *z;
    if((z=search(root,key))!=NULL)
        root = remove(root,z);
}

完整实现

头文件:AVLTree.h

#ifndef AVL_TREE
#define AVL_TREE
 
#include<iomanip>
#include<iostream>
using namespace std;
 
template<class T>
class AVLTreeNode
{
    public:
        T key;    // 关键字(键值)
        int height;    // 高度
        AVLTreeNode *left;    // 左孩子
        AVLTreeNode *right;    // 右孩子
    
        AVLTreeNode(T value, AVLTreeNode *l, AVLTreeNode *r) :
            key(value) ,left(l),right(r) {}
};
 
template<class T>
class AVLTree
{
    private:
        AVLTreeNode<T> *root;    // 根结点
    
    public:
        // 外部接口 
         AVLTree();
         ~AVLTree();
         
        // 获取树的高度
        int height();
        // 比较两个值的大小 
        int max(int a, int b);
        
        // 前序遍历
        void preOrder();
        // 中序遍历
        void inOrder();
        // 后序遍历
        void postOrder();
        
        // (递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* search(T key);
        // (非递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* iterativeSearch(T key);
        
        // 查找最小结点:返回最小结点的键值
        T minimum();
        // 查找最大结点:返回最大结点的键值
        T maximum();
        
        // 将结点插入到AVL树中
        void insert(T key);
        // 删除结点
        void remove(T key);
        
        // 销毁AVL树
        void destroy();
        
        // 打印AVL树
        void print();
    
    private:
        // 内部接口 
        // 获取树的高度
        int height(AVLTreeNode<T> *tree);
        
        // 前序遍历
        void preOrder(AVLTreeNode<T> *tree) const;
        // 中序遍历
        void inOrder(AVLTreeNode<T> *tree) const;
        // 后序遍历
        void postOrder(AVLTreeNode<T> *tree) const;
        
        // (递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* search(AVLTreeNode<T> *x, T key) const;
        // (非递归实现)查找AVL树中键值为key的结点
        AVLTreeNode<T>* iterativeSearch(AVLTreeNode<T> *x, T key) const;
        
        // 返回最小结点 
        AVLTreeNode<T>* minimum(AVLTreeNode<T> *tree);
        // 返回最大结点 
        AVLTreeNode<T>* maximum(AVLTreeNode<T> *tree);
        
        // 将结点插入到AVL树中
        AVLTreeNode<T>* insert(AVLTreeNode<T>* &tree, T key);
        // 删除结点,并返回被删除的结点 
        AVLTreeNode<T>* remove(AVLTreeNode<T>* &tree, AVLTreeNode<T> *z);
        
        // 销毁AVL树
        void destroy(AVLTreeNode<T>* &tree);
        
        // 打印AVL树
        void print(AVLTreeNode<T> *tree,T key,int direction);
        
        // LL:左左对应的情况(左单旋转)
        AVLTreeNode<T>* leftLeftRotation(AVLTreeNode<T> *k2);
        // RR:右右对应的情况(右单旋转)
        AVLTreeNode<T>* rightRightRotation(AVLTreeNode<T> *k1);
        // LR:左右对应的情况(左双旋转)
        AVLTreeNode<T>* leftRightRotation(AVLTreeNode<T> *k3);
        // RL:右左对应的情况(右双旋转)
        AVLTreeNode<T>* rightLeftRotation(AVLTreeNode<T> *k1);    
};
 
template<class T>
AVLTree<T>::AVLTree(): root(NULL)
{
}
 
template<class T>
AVLTree<T>::~AVLTree()
{
    destroy(root);
}
 
template<class T>
int AVLTree<T>::height(AVLTreeNode<T> *tree)
{
    if(tree!=NULL)
        return tree->height;
    return 0;
}
 
template<class T>
int AVLTree<T>::height()
{
    return height(root);
}
 
template<class T>
int AVLTree<T>::max(int a, int b)
{
    return a>b ? a : b;
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::leftLeftRotation(AVLTreeNode<T> *k2)
{
    AVLTreeNode<T> *k1;
    
    k1 = k2->left;
    k2->left = k1->right;
    k1->right = k2;
    
    k2->height = max(height(k2->left), height(k2->right)) + 1;
    k1->height = max(height(k1->left), k2->height) + 1;
    
    return k1;
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::rightRightRotation(AVLTreeNode<T> *k1)
{
    AVLTreeNode<T> *k2;
    
    k2 = k1->right;
    k1->right = k2->left;
    k2->left = k1;
    
    k1->height = max(height(k1->left), height(k1->right)) + 1;
    k2->height = max(k1->height, height(k2->right)) + 1;
    
    return k2; 
}
 
template <class T>
AVLTreeNode<T>* AVLTree<T>::leftRightRotation(AVLTreeNode<T>* k3)
{
    k3->left = rightRightRotation(k3->left);
    
    return leftLeftRotation(k3);
}
 
template <class T>
AVLTreeNode<T>* AVLTree<T>::rightLeftRotation(AVLTreeNode<T>* k1)
{
    k1->right = leftLeftRotation(k1->right);
    
    return rightRightRotation(k1);
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::insert(AVLTreeNode<T>* &tree, T key)
{
    if(tree==NULL)
    {
        // 新建结点 
        tree = new AVLTreeNode<T>(key, NULL, NULL);
        if(tree==NULL)
        {
            cout<<"ERROR: create avltree node failed!"<<endl;
            return NULL;
        }
    }
    else if(key<tree->key)
    {
        tree->left = insert(tree->left, key);
        // 插入结点后,若AVL树失去平衡,则进行相应的调节
        if(height(tree->left)-height(tree->right)==2)
        {
            if(key<tree->left->key)
                tree = leftLeftRotation(tree);
            else
                tree = leftRightRotation(tree);
        } 
    }
    else
    {
        tree->right = insert(tree->right, key);
        // 插入结点后,若AVL树失去平衡,则进行相应的调节
        if(height(tree->right)-height(tree->left)==2)
        {
            if(key>tree->right->key)
                tree = rightRightRotation(tree);
            else
                tree = rightLeftRotation(tree);
        } 
    }
    
    tree->height = max(height(tree->left), height(tree->right)) + 1;
    
    return tree;
}
 
template<class T>
void AVLTree<T>::insert(T key)
{
    insert(root,key);
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::remove(AVLTreeNode<T>* &tree, AVLTreeNode<T> *z)
{
    // 根为空 或者 没有要删除的结点
    if(tree==NULL || z==NULL)
        return NULL;
    if(z->key<tree->key)
    {
        tree->left = remove(tree->left, z);
        // 删除结点后,若AVL树失去平衡,则进行相应调节
        if(height(tree->right)-height(tree->left)==2)
        {
            AVLTreeNode<T> *r = tree->right;
            if(height(r->left)>height(r->right))
                tree = rightLeftRotation(tree);
            else
                tree = rightRightRotation(tree);
        } 
    } 
    else if(z->key>tree->key)
    {
        tree->right = remove(tree->right, z);
        if(height(tree->left)-height(tree->right)==2)
        {
            AVLTreeNode<T> *r = tree->left;
            if(height(r->left)<height(r->right))
                tree = leftRightRotation(tree);
            else
                tree = leftLeftRotation(tree);
        }
    }
    else    // tree是对应要删除的结点 
    {
        // tree的左右孩子都非空 
        if((tree->left!=NULL)&&(tree->right!=NULL))
        {
            if(height(tree->left)>height(tree->right))
            {
                // 如果tree的左子树比右子树高;
                // 则(01)找出tree的左子树中的最大节点
                //   (02)将该最大节点的值赋值给tree。
                //   (03)删除该最大节点。
                // 这类似于用"tree的左子树中最大节点"做"tree"的替身;
                // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
                AVLTreeNode<T> *max = maximum(tree->left);
                tree->key = max->key;
                tree->left = remove(tree->left, max);
            }
            else
            {
                // 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
                // 则(01)找出tree的右子树中的最小节点
                //   (02)将该最小节点的值赋值给tree。
                //   (03)删除该最小节点。
                // 这类似于用"tree的右子树中最小节点"做"tree"的替身;
                // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
                AVLTreeNode<T> *min = minimum(tree->right);
                tree->key = min->key;
                tree->right = remove(tree->right, min); 
            }
        }
        else
        {
            AVLTreeNode<T> *tmp = tree;
            tree = (tree->left!=NULL) ? tree->left : tree->right;
            delete tmp;
        }
    }
    
    return tree;
}
 
template<class T>
void AVLTree<T>::remove(T key)
{
    AVLTreeNode<T> *z;
    if((z=search(root,key))!=NULL)
        root = remove(root,z);
}
 
template<class T>
void AVLTree<T>::preOrder(AVLTreeNode<T> *tree) const
{
    if(tree!=NULL)
    {
        cout<<tree->key<<" ";
        preOrder(tree->left);
        preOrder(tree->right);
    }
}
 
template<class T>
void AVLTree<T>::preOrder()
{
    preOrder(root);
}
 
template<class T>
void AVLTree<T>::inOrder(AVLTreeNode<T> *tree) const
{
    if(tree!=NULL)
    {
        inOrder(tree->left);
        cout<<tree->key<<" ";
        inOrder(tree->right);
    }
}
 
template<class T>
void AVLTree<T>::inOrder()
{
    inOrder(root);
}
 
template<class T>
void AVLTree<T>::postOrder(AVLTreeNode<T> *tree) const
{
    if(tree!=NULL)
    {
        postOrder(tree->left);
        postOrder(tree->right);
        cout<<tree->key<<" ";
    }
}
 
template<class T>
void AVLTree<T>::postOrder()
{
    postOrder(root);
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::search(AVLTreeNode<T> *x, T key) const
{
    if(x==NULL || x->key==key)
        return x;
    if(key<x->key)
        return search(x->left, key);
    else
        return search(x->right, key);
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::search(T key)
{
    return search(root, key);
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::iterativeSearch(AVLTreeNode<T> *x, T key) const
{
    while(x!=NULL && x->key!=key)
    {
        if(key<x->key)
            x = x->left;
        else
            x = x->right;
    }
    return x;
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::iterativeSearch(T key)
{
    return iterativeSearch(root, key);
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::minimum(AVLTreeNode<T> *tree)
{
    if(tree==NULL)
        return NULL;
    while(tree->left!=NULL)
        tree = tree->left;
    return tree;
}
 
template<class T>
T AVLTree<T>::minimum()
{
    AVLTreeNode<T> *p = minimum(root);
    if(p!=NULL)
        return p->key;
    return (T)NULL;
}
 
template<class T>
AVLTreeNode<T>* AVLTree<T>::maximum(AVLTreeNode<T> *tree)
{
    if(tree==NULL)
        return NULL;
    while(tree->right!=NULL)
        tree = tree->right;
    return tree;
}
 
template<class T>
T AVLTree<T>::maximum()
{
    AVLTreeNode<T> *p = maximum(root);
    if(p!=NULL)
        return p->key;
    return (T)NULL;
}
 
template<class T>
void AVLTree<T>::destroy(AVLTreeNode<T> *&tree)
{
    if(tree==NULL)
        return ;
    if(tree->left!=NULL)
        destroy(tree->left);
    if(tree->right!=NULL)
        destroy(tree->right);
    delete tree;
}
 
template<class T>
void AVLTree<T>::destroy()
{
    destroy(root);
}
 
template<class T>
void AVLTree<T>::print(AVLTreeNode<T> *tree, T key, int direction)
{
    if(tree!=NULL)
    {
        if(direction==0)
            cout<<setw(2)<<tree->key<<"is root"<<endl;
        else
            cout<<setw(2)<<tree->key<<"is"<<setw(2)<<key<<"'s"<<setw(12)<<(direction==1 ? "right child" : "left child")<<endl;
        print(tree->left, tree->key, -1);
        print(tree->right, tree->key, 1);
    }
}
 
template<class T>
void AVLTree<T>::print()
{
    if(root!=NULL)
        print(root, root->key, 0);
}
 
#endif
 
 

测试文件:AVLTreeTest.cpp

#include<iostream>
#include "AVLTree.h"
using namespace std;
 
static int arr[] = {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
int main()
{
	int i,len;
	AVLTree<int> *tree = new AVLTree<int>();
	
	cout<<"依次添加:";
	len = sizeof(arr)/sizeof(arr[0]);
	for(i=0;i<len;++i)
	{
		cout<<arr[i]<<" ";
		tree->insert(arr[i]);
	}
	cout<<"\n前序遍历:";
	tree->preOrder();
	cout<<"\n中序遍历:";
	tree->inOrder();
	cout<<"\n后序遍历:";
	tree->postOrder();
	
	cout<<"\n高度: "<<tree->height()<<endl;
    cout<<"最小值: "<<tree->minimum()<<endl;
    cout<<"最大值: "<<tree->maximum()<<endl;
    cout<<"树的详细信息: "<<endl;
    tree->print();
    
    i = 8;
    cout<<"\n删除根节点:"<<i;
    tree->remove(i);
    
    cout<<"\n高度: "<<tree->height()<<endl;
    cout<<"中序遍历:";
    tree->inOrder();
    cout<<"\n树的详细信息: "<<endl;
    tree->print();
    
    // 销毁二叉树
	tree->destroy();
	return 0; 
}

测试程序示意图:

 

(1)添加3,2:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

(2)添加1:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

(3)添加4:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

(4)添加5:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

(5)… ….

(6)添加完所有数据后,得到的AVL树如下:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

 

(7)删除节点8:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

 

程序运行结果如下:

《【数据结构与算法分析】第四章 树-AVL树 (三)》

《【数据结构与算法分析】第四章 树-AVL树 (三)》

 参考资料:

感谢作者如果天空不死 :AVL树

    原文作者:AVL树
    原文地址: https://blog.csdn.net/zhangxiafll/article/details/81742313
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞