树-AVL最优二叉树

AVL树

#include<iostream>
using namespace std;

class Node{
public:
    int data;
    Node* left;
    Node* right;
    Node():left(NULL),right(NULL),data(0){}
    Node(int data):data(data),left(NULL),right(NULL){}
};
class AVLTree{
    Node* root;
    Node* treeMax(Node* root){
        while(root->right){
            root = root->right;
        }
        return root;
    }
    bool _isNodeWithTwoChild(Node* root){
        if((root->left)&&(root->right)){
            return true;
        }else{
            return false;
        }
    }
    Node* _search(Node* root,int k){
        if(root==NULL){
            return root;
        }
        if((root->data)>k){
            return _search(root->left,k);
        }else if((root->data)<k){
            return _search(root->right,k);
        }else if((root->data)==k){
            return root;
        }
    }
    int _height(Node* root){
        if(root==NULL){
            return 0;
        }else{
            return max(_height(root->left),_height(root->right))+1;
        }
    }
    int _diff(Node* root){
        return _height(root->left) - _height(root->right);
    }
    Node* ll_Rotation(Node* root){
        Node* tmp = root->left;
        root->left = tmp->right;
        tmp->right = root;
        return tmp;
    }
    Node* rr_Rotation(Node* root){
        Node* tmp = root->right;
        root->right = tmp->left;
        tmp->left = root;
        return tmp;
    }
    Node* lr_Rotation(Node* root){
        Node* tmp1 = root->left;
        root->left = rr_Rotation(tmp1);
        return ll_Rotation(root);
    }
    Node* rl_Rotation(Node* root){
        Node* tmp = root->right;
        root->right = ll_Rotation(tmp);
        return rr_Rotation(root);
    }
    Node* _Balance(Node* root){
        int balance = _diff(root);
        if(balance > 1){
            if(_diff(root->left) > 0){
                return ll_Rotation(root);
            }else{
                return lr_Rotation(root);
            }
        }else if(balance<-1){
            if(_diff(root->right) > 0){
                return rl_Rotation(root);
            }else{
                return rr_Rotation(root);
            }
        }
        return root;
    }
    Node* _insert(Node* root,int key){
        if(root == NULL){
            Node* tmp;
            tmp->data = key;
            root = tmp;
            return root;
        }else if(key<root->data){
            root->left = _insert(root->left,key);
            root = _Balance(root);
        }else if(key>root->data){
            root->left = _insert(root->right,key);
            root = _Balance(root);
        }
        return root;
    }
    Node* _delete(Node* root,int key){
        Node* tmp;tmp = root;
        if(root == NULL){
            return root;
        }
        if(!_search(tmp,key)){
            cout<<"Sorry do not find!"<<endl;
            return root;
        }
        if(key == root->data){
            if(_isNodeWithTwoChild(root)){
                if(_diff(root)>0){
                    root->data = treeMax(root->left)->data;
                    _delete(root->left,root->data);
                }else{
                    root->data = treeMax(root->right)->data;
                    _delete(root->right,root->data);
                }
            }else{
                Node* tmp = root;
                root = (root->left)?(root->left):(root->right);
                delete tmp;
                tmp = NULL;
            }
        }else if(key < root->data){
            root->left = _delete(root->left,key);
            if(_diff(root->right)>0){
                root = rl_Rotation(root);
            }else{
                root = rr_Rotation(root);
            }
        }else{
            root->right = _delete(root->right,key);
            if(_diff(root) > 1){
                if(_diff(root->left) < 0){
                    root = lr_Rotation(root);
                }else{
                    root = ll_Rotation(root);
                }
            }
        }
        return root;
    }
};

AVL模板

忘记是哪位大神的了,是我半年前学习的模板。(侵删)

#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(AVLNode *t, ostream & out) const;
	/**
	* 按中序打印子树
	*/

	void inOrder(AVLNode *t, ostream & out) const;
	/**
	* 按后序打印子树
	*/
	void postOrder(AVLNode *t, ostream & out) const;

	/**
	* 复制子树
	*/
	AVLNode * clone(AVLNode *t) const;

	/**
	* 平衡子树
	*/
	void balance(AVLNode * &t);

	/**
	* 左旋(右子树比左子树高2,并且新插入的元素在右子树的右边)
	* 此时以右子树(k1)为轴,它的根(k2)进行左旋
	* 可以理解为它的根在它的左边,所以左旋(在左边旋转)
	*      K2                           K1
	*     /  \                         /  \
	*    X    k1         -----        K2   Z
	*         / \                    /  \   \
	*        Y   Z                  X    Y   Z'
	*             \
	*              Z'
	* Z'可能在Z的左边,也可以在Z的右边。例子中假设在右边。
	**/
	void rotateWithRightChild(AVLNode * & k2);

	/**
	* 右旋(左子树比右子树高2,并且新插入的元素在左子树的左边)
	* 此时以左子树(k1)为轴,它的根(k2)进行右旋
	* 可以理解为它的根在它的右边,所以右旋(在右边旋转)
	*       k2                      k1
	*      /  \                    /  \
	*     k1   Z      -------     X    k2
	*    /  \                    /     / \
	*   X    Y                  X'     Y   Z
	*  /
	* X'
	* X'可能在X的左边,也可以在X的右边。例子中假设在左边。
	*/
	void rotateWithLeftChild(AVLNode * & k2);

	/**
	* 左右双旋(左子树K1比右子树D高2,并且新插入的元素在左子树K1的右边K2)
	* 第一步:对左子树k1进行一次左旋(轴为k2)
	* 第二步:对整个树k3进行一次右旋(轴为k2)
	*       k3                k3              k2
	*      /  \              /  \            /  \
	*     k1   D    ----    k2   D  ----    k1   k3
	*    / \               / \             / \   / \
	*   A   k2            k1  C           A   B  C  D
	*       / \          / \
	*      B   C        A   B
	*/
	void doubleWithLeftChild(AVLNode * & k3);

	/**
	* 右左双旋(右子树K1比左子树A高2,并且新插入的元素在右子树K1的左边K2)
	* 第一步:对右子树k1进行一次右旋(轴为k2)
	* 第二步:对整个树k3进行一次左旋(轴为k2)
	*      k3              k3                 k2
	*     /  \            /  \               /  \
	*    A    k1   ----  A    k2     ----  k3    k1
	*        / \             /  \         /  \  /  \
	*       K2  D           B    k1      A    B C   D
	*      / \                  /  \
	*     B   C                C    D
	*/
	void doubleWithRightChild(AVLNode * & k3);

	/**
	* 更新节点的高度
	*/
	inline void updateHeight(AVLNode * & t)
	{
		t->height = max(height(t->left), height(t->right)) + 1;
	}

};


/**
* 复制子树
*/
template <typename Comparable>
typename AVLTree<Comparable>::AVLNode *
	AVLTree<Comparable>::clone(
		typename AVLTree<Comparable>::AVLNode *t) const
{
	if (t == nullptr)
		return nullptr;

	return new AVLNode(t->element, clone(t->left), clone(t->right));
}

/**
* 按前序打印子树
*/
template <typename Comparable>
void AVLTree<Comparable>::preOrder(
	typename AVLTree<Comparable>::AVLNode*t,
	ostream & out) const
{
	if (nullptr != t)
	{
		out << t->element << endl;
		preOrder(t->left, out);
		preOrder(t->right, out);
	}
}



/**
* 按中序打印子树
*/
template <typename Comparable>
void AVLTree<Comparable>::inOrder(
	typename AVLTree<Comparable>::AVLNode *t,
	ostream & out) const
{
	if (nullptr != t)
	{
		inOrder(t->left, out);
		out << t->element << endl;
		inOrder(t->right, out);
	}
}

/**
* 按后序打印子树
*/
template <typename Comparable>
void AVLTree<Comparable>::postOrder(
	typename AVLTree<Comparable>::AVLNode*t,
	ostream & out) const
{

	if (nullptr != t)
	{
		postOrder(t->left, out);
		postOrder(t->right, out);
		out << t->element << endl;
	}
}


/**
* 清空树
*/
template <typename Comparable>
void AVLTree<Comparable>::makeEmpty(
	typename AVLTree<Comparable>::AVLNode * &t)
{
	if (t != nullptr)
	{
		makeEmpty(t->left);
		makeEmpty(t->right);
		delete t;
	}
	t = nullptr;
}

/**
* 查找最小的元素, 通过递归的方法
*/
template <typename Comparable>
typename AVLTree<Comparable>::AVLNode *
	AVLTree<Comparable>::findMin(
	typename AVLTree<Comparable>::AVLNode *t) const
{
	if (t == nullptr)
		return nullptr;
	if (t->left == nullptr)
		return t;
	return findMin(t->left);
}

/**
* 查找最大的元素, 通过循环的方法
*/
template <typename Comparable>
typename AVLTree<Comparable>::AVLNode *
	AVLTree<Comparable>::findMax(
	typename AVLTree<Comparable>::AVLNode *t) const
{
	if (t != nullptr)
		while (t->right != nullptr)
			t = t->right;
	return t;
}

/**
* 在树t中删除元素x,一定要主要保持树的平衡
*/
template <typename Comparable>
void AVLTree<Comparable>::remove(
	const Comparable &x,
	typename AVLTree<Comparable>::AVLNode * &t)
{
	if (t == nullptr)
		return; // 没有找要删除的节点x

	if (x < t->element)
		remove(x, t->left);
	else if (t->element < x)
		remove(x, t->right);
	else if (t->left != nullptr &&
		t->right != nullptr)
	{
		t->element = findMin(t->right)->element;
		remove(t->element, t->right);
	}
	else
	{
		//typename AVLTree<Comparable>::AVLNode * oldNode = t;
		auto oldNode = t; // 这一句等于上面的那长长的语句,可以看出C++11中的auto还是非常有用 的
		t = (t->left != nullptr) ? t->left : t->right;
		delete oldNode;
	}

	balance(t);
}

/**
* 在树t中插入元素x,如果重复则什么也不做
*/
template <typename Comparable>
void AVLTree<Comparable>::insert(
	const Comparable &x,
	typename AVLTree<Comparable>::AVLNode * &t)
{
	if (nullptr == t)
		t = new AVLNode(x, nullptr, nullptr);
	else if (x < t->element)
	{
		insert(x, t->left); // 如果带插入的值小于目前的节点,则插入在左子树
		/*
		if (height(t->left) - height(t->right) == 2) // 插入后如果节点的左子树比右子树高2
		{
			if (x < t->left->element)
				rotateWithLeftChild(t); // 右旋
			else
				doubleWithLeftChild(t); // 左-右双旋
		}
		*/

	}
	else if (t->element < x)
	{
		insert(x, t->right);// 如果带插入的值大于目前的节点,则插入在右子树
		/*
		if (height(t->right) - height(t->left) == 2)// 插入后如果节点的右子树比左子树高2
		{
			if (t->right->element < x)
				rotateWithRightChild(t); // 左旋
			else
				doubleWithRightChild(t); // 右-左双旋
		}
		*/

	}
	else
		; // 表示在树中找到了x,则什么也不做

	balance(t); // 每次完成插入都检查子树是否平衡(并且默认更新节点t的高度)
}

/**
* 平衡子树
*/
template <typename Comparable>
void AVLTree<Comparable>::balance(
	typename AVLTree<Comparable>::AVLNode * &t)
{
	if (nullptr == t)
		return;
	// 如果左子树的高度与右子树高度差大于实施平衡调整的限度
	if (height(t->left) - height(t->right) > AVLTree<Comparable>::ALLOW_IMBALANCE)
	{
		// 判断是左子树的左边高还是右边高,如果左子树左边高
		if (height(t->left->left) >= height(t->left->right))
		{
			rotateWithLeftChild(t);
		}
		else
		{
			doubleWithLeftChild(t);
		}

	}
	// 如果右子树的高度与左子树高度差大于实施平衡调整的限度
	else if (height(t->right) - height(t->left) > AVLTree<Comparable>::ALLOW_IMBALANCE)
	{
		if (height(t->right->right) >= height(t->right->left))
		{
			rotateWithRightChild(t);
		}
		else
		{
			doubleWithRightChild(t);
		}
	}
	else
		;

	updateHeight(t);
}

/**
* 通过遍历的方法查找x是否在树(或子树)t中
*/
template <typename Comparable>
bool AVLTree<Comparable>::contains(
	const Comparable &x,
	typename AVLTree<Comparable>::AVLNode * t) const
{
	if (t == nullptr) // 遍历中未找到元素的中止条件
		return false;
	else if (x < t->element)
		return contains(x, t->left);
	else if (t->element < x)
		return contains(x, t->right);
	else // 如果 x 不大于 也 不小于t所指的节点中的元素,则x==t->element
		return true;
}

/**
* 右旋(左子树比右子树高2,并且新插入的元素在左子树的左边)
* 此时以左子树(k1)为轴,它的根(k2)进行右旋
* 可以理解为它的根在它的右边,所以右旋(在右边旋转)
*       k2                      k1
*      /  \                    /  \
*     k1   Z      -------     X    k2
*    /  \                    /     / \
*   X    Y                  X'     Y   Z
*  /
* X'
* X'可能在X的左边,也可以在X的右边。例子中假设在左边。
*/
template <typename Comparable>
void AVLTree<Comparable>::rotateWithLeftChild(
	typename AVLTree<Comparable>::AVLNode * & k2)
{
	//typename AVLTree<Comparable>::AVLNode * k1 = k2->left; // 获得k2的左节点
	auto k1 = k2->left; // 使用auto定义
	// 开始旋转
	k2->left = k1->right;
	k1->right = k2;
	//更新高度, 先更新k2可以,更新k1时减少一次height函数的调用
	k2->height = max(height(k2->left), height(k2->right)) + 1;//等价于updateHeight(k2)
	k1->height = max(height(k1->left), k2->height) + 1;

	k2 = k1;

}

/**
* 左旋(右子树比左子树高2,并且新插入的元素在右子树的右边)
* 此时以右子树(k1)为轴,它的根(k2)进行左旋
* 可以理解为它的根在它的左边,所以左旋(在左边旋转)
*      K2                           K1
*     /  \                         /  \
*    X    k1         -----        K2   Z
*         / \                    /  \   \
*        Y   Z                  X    Y   Z'
*             \
*              Z'
* Z'可能在Z的左边,也可以在Z的右边。例子中假设在右边。
**/
template <typename Comparable>
void AVLTree<Comparable>::rotateWithRightChild(
	typename AVLTree<Comparable>::AVLNode * & k2)
{
	//typename AVLTree<Comparable>::AVLNode * k1 = k2->right;
	auto k1 = k2->right; // 使用auto定义
	// 开始旋转
	k2->right = k1->left;
	k1->left = k2;
	//更新高度, 先更新k2可以减少一次height函数的调用
	k2->height = max(height(k2->left), height(k2->right)) + 1;
	k1->height = max(k2->height, height(k1->right)) + 1;

	k2 = k1;
}

/**
* 左右双旋(左子树K1比右子树D高2,并且新插入的元素在左子树K1的右边K2)
* 第一步:对左子树k1进行一次左旋(轴为k2)
* 第二步:对整个树k3进行一次右旋(轴为k2)
*       k3                k3              k2
*      /  \              /  \            /  \
*     k1   D    ----    k2   D  ----    k1   k3
*    / \               / \             / \   / \
*   A   k2            k1  C           A   B  C  D
*       / \          / \
*      B   C        A   B
* 注:一般来说,只会有B或C一个存在,就会进行树的平衡调整
*/
template <typename Comparable>
void AVLTree<Comparable>::doubleWithLeftChild(
	typename AVLTree<Comparable>::AVLNode * & k3)
{
	rotateWithRightChild(k3->left);
	rotateWithLeftChild(k3);
}


/**
* 右左双旋(右子树K1比左子树A高2,并且新插入的元素在右子树K1的左边K2)
* 第一步:对右子树k1进行一次右旋(轴为k2)
* 第二步:对整个树k3进行一次左旋(轴为k2)
*      k3              k3                 k2
*     /  \            /  \               /  \
*    A    k1   ----  A    k2     ----  k3    k1
*        / \             /  \         /  \  /  \
*       K2  D           B    k1      A    B C   D
*      / \                  /  \
*     B   C                C    D
*注:一般来说,只会有B或C一个存在,就会进行树的平衡调整
*/
template <typename Comparable>
void AVLTree<Comparable>::doubleWithRightChild(
	typename AVLTree<Comparable>::AVLNode * & k3)
{
	rotateWithLeftChild(k3->right);
	rotateWithRightChild(k3);
}
#endif  //AVL_TREE_H

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值