今天练习编写了一下AVL树。参考了Weiss的数据结构与算法C++描述版。上一个实现了一般的二叉搜索树,在使用的过程中可能会慢慢变得不平衡,这样很可能会降低查找、插入等等的效率,因此我们需要使用算法来实现树的平衡。AVL树是一种比较经典的平衡二叉搜索树,它规定每个节点的左子树和右子树的高度差最多为1,默认空树的高度为-1,这样能保证树的深度为O(logN),而且除了遍历,赋值,基本上所有树的操作都可以以时间O(logN)执行(当然插入和删除后因为要重新平衡树,可能时间会长于O(logN))。(Ps,上面文字中的log指log2)
AVL树中,最重要的便是让树重新平衡,我们称个过程为旋转。旋转包括四种,主要是由于插入位置的原因导致的。旋转的过程可以看代码中的注释部分(569行-639行),有详细的解释。
这次编写的过程中,将C++模板类的定义了和函数实现进行了分开(但是仍然在头文件中),遇到了比较多的问题。先看看代码,然后对里面我遇到的问题进行总结。
先看看AVL树的实现代码 AVLTree.h:
#ifndef AVL_TREE_H
#define AVL_TREE_H
#include<iostream>
using namespace std;
template <typename Comparable>
class AVLTree
{
public:
typedef enum _order {PREORDER, INORDER, POSTORDER} ORDER; // 通过enum定义常量
public:
AVLTree() :m_root(nullptr){}
AVLTree(const AVLTree &rhs)
{
m_root = clone(rhs.m_root);
}
~AVLTree()
{
makeEmpty();
}
/**
* 返回树的高度。空树的高度定义为-1
*/
int getHeight() const
{
return m_root.height;
}
/**
* 找到树中的最小值,通过调用private的findMin实现递归
*/
const Comparable & findMin() const
{
return findMin(m_root)->element;
}
/**
* 找到树中的最大值,通过调用private的findMax实现递归
*/
const Comparable & findMax() const
{
return findMax(m_root)->element;
}
/**
* 当x找到时返回真,否则返回假
* 调用了private的那个同名函数,这个是为了递归实现
*(因为private中包含了一个AVLNode的指针t)
*/
bool contains(const Comparable &x) const
{
return contains(x, m_root);
}
/**
* 判断树是否为空
*/
bool isEmpty() const
{
return nullptr == m_root;
}
/**
* 把树遍历一遍(顺序可以自己选择,默认为中序)
*/
void printTree(ORDER or = INORDER, ostream & out = cout) const
{
if (isEmpty())
out << "Empty tree!" << endl;
else
{
switch (or)
{
case PREORDER:
preOrder(m_root, cout);
break;
case INORDER:
inOrder(m_root, cout);
break;
case POSTORDER:
postOrder(m_root, cout);
break;
default:
cerr << "打印树的顺序只能为PREORDER, INORDER, POSTORDER!" << endl;
break;
}
}
}
/**
* 清空树
*/
void makeEmpty()
{
makeEmpty(m_root);
}
/**
* 把x插入树中,如果重复了就忽略
*/
void insert(const Comparable &x)
{
insert(x, m_root);
}
/**
* 把x从树中删除。如果x不在树中就什么都不做。
*/
void remove(const Comparable &x)
{
remove(x, m_root);
}
/**
* 深拷贝
*/
const AVLTree & operator= (const AVLTree &rhs)
{
if (this != &rhs)
{
AVLNode *tmp = clone(rhs.m_root);
makeEmpty();
m_root = tmp;
}
return *this;
}
private:
struct AVLNode{
Comparable element;
AVLNode *left;
AVLNode *right;
int height;
AVLNode(const Comparable &theElement,
AVLNode *lt,
AVLNode *rt,
int h = 0)
: element(theElement), left(lt), right(rt), height(h) {}
};
AVLNode *m_root; // 根节点
static const int ALLOW_IMBALANCE = 1; // 允许实施平衡的高度界限
/**
* 用于比较两个数的大小(主要用于比较高度)
*/
int max (int a, int b)
{
return a >= b ? a : b;
}
/**
* 获得节点高度,空树的高度为-1
*/
inline int height(AVLNode *t) const
{
return nullptr == t ? -1 : t->height;
}
/**
* 在树t中插入元素x,如果重复则什么也不做
*/
void insert(const Comparable &x, AVLNode * &t);
/**
* 在树t中删除元素x
*/
void remove(const Comparable &x, AVLNode * &t);
/**
* 查找最小的元素, 通过递归的方法
*/
AVLNode * findMin(AVLNode *t) const;
/**
* 查找最大的元素, 通过循环的方法
*/
AVLNode * findMax(AVLNode *t) const;
/**
* 通过遍历的方法查找x是否在树(或子树)t中
*/
bool contains(const Comparable &x, AVLNode * t) const;
/**
* 清空树
*/
void makeEmpty(AVLNode * &t);
/**
* 按前序打印子树
*/
void preOrder(AV