使用C++实现AVL树模板

本文介绍了如何使用C++实现AVL树,包括树的平衡性质、旋转操作及其在代码中的实现。详细讲解了AVLNode结构、高度计算、遍历方式、静态常量以及旋转函数的实现细节,同时分享了在模板类中分离成员函数实现时遇到的问题和解决方案。最后通过测试代码验证了AVL树的正确性和平衡性。
摘要由CSDN通过智能技术生成

今天练习编写了一下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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值