赞
踩
如果二叉排序树的左、右子树的高度之差的绝对值不超过1,这样的排序二叉树称为平衡二叉树,它的平均查找长度达到O(log2n)。
为了避免树的高度增长过快,降低二叉排序树的性能,我们规定在插入和删除二叉树结点时,要保证任意结点的左、右子树高度差的绝对值不超过1。这样的二叉树称为平衡二叉树。
平衡二叉树可定义为它或是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的高度差的绝对值不超过1。
需要注意的有以下两点:
插入操作中:
LR和RL旋转的时候,调用LL和RR旋转,其原因是这样做复合LR和RL的最终要求,这里调用LL(RR)旋转函数,不是说
在左子树的左子树(右子树的右子树)插入了结点,而只是为了可以达到LR(RL)的最终形态。这里也可以不调用LL和RR函数,对指针进行操作也可以,不过需要对四代指针进行操作,比较麻烦。
删除操作(难点):
同插入操作一样,删除结点时也有可能破坏平衡性,这就要求我们删除的时候要进行平衡性调整。
删除分为以下几种情况:
首先在整个二叉树中搜索要删除的结点,如果没搜索到直接返回不作处理,否则执行以下操作:
1.要删除的节点是当前根节点T。
如果左右子树都非空。在高度较大的子树中实施删除操作。
分两种情况:
(1)、左子树高度大于右子树高度,将左子树中最大的那个元素赋给当前根节点,然后删除左子树中元素值最大的那个节点。
(2)、左子树高度小于右子树高度,将右子树中最小的那个元素赋给当前根节点,然后删除右子树中元素值最小的那个节点。
如果左右子树中有一个为空,那么直接用那个非空子树或者是NULL替换当前根节点即可。
2、要删除的节点元素值小于当前根节点T值,在左子树中进行删除。
递归调用,在左子树中实施删除。这个是需要判断当前根节点是否仍然满足平衡条件,如果满足平衡条件,只需要更新当前根节点T的高度信息。否则,需要进行旋转调整:如果T的左子节点的左子树的高度大于T的左子节点的右子树的高度,进行相应的单旋转。否则进行双旋转。
3、要删除的节点元素值大于当前根节点T值,在右子树中进行删除。
- #include <iostream>
- #include <queue>
- #include <stack>
- using namespace std;
-
- template <typename T>
- struct avlTreeNode{
- T data;
- int height;
- avlTreeNode* left;
- avlTreeNode* right;
- avlTreeNode(T val, avlTreeNode<T>* l, avlTreeNode<T>* r):data(val), height(0), left(l), right(r){}
- };
-
- template <typename T>
- class avlTree{
- private:
- avlTreeNode<T>* root;
- int max(int a, int b){return a > b ? a : b;}
- public:
- avlTree(){root = NULL;}
- avlTreeNode<T>*& getRoot(){return root;}
- int getHeight(avlTreeNode<T>* ptr);//获得子树的高度
- void llRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行LL平衡旋转
- void lrRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行LR平衡旋转
- void rrRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行RR平衡旋转
- void rlRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行RL平衡旋转
- void addValue(avlTreeNode<T>* &root, T val);//向平衡树中增加结点
- void delValue(avlTreeNode<T>* &root, T val);//删除值val所在结点
- void creatAvlTree();//建立平衡树
- avlTreeNode<T>* getMin(avlTreeNode<T>* root) const;//找到以root为根节点的树中最小的节点
- avlTreeNode<T>* getMax(avlTreeNode<T>* root) const;//找到以root为根节点的树中最大的节点
- void printAvlTreeOfPre() const;//先序遍历输出结果
- void printAvlTreeOfIn() const;//中序遍历输出结果
- };
-
- template <typename T>
- int avlTree<T>::getHeight(avlTreeNode<T>* ptr){
- if(ptr != NULL)
- return ptr -> height;
- return 0;
- }
-
- template <typename T>
- void avlTree<T>::llRotation(avlTreeNode<T>* &root){
- //进行右单旋转,这里需要注意的是需要对两个结点的高度进行调整
- avlTreeNode<T>* temp = root;
-
- root = root -> left;
- temp -> left = root -> right;
- root -> right = temp;
-
- temp -> height = max(getHeight(temp -> left), getHeight(temp -> right)) + 1;
- root -> height = max(getHeight(root -> left), getHeight(root -> right)) + 1;
- }
-
- template <typename T>
- void avlTree<T>::rrRotation(avlTreeNode<T>* &root){
- //进行左单旋转,这里需要注意的是需要对两个结点的高度进行调整
- avlTreeNode<T>* temp = root;
-
- root = root -> right;
- temp -> right = root -> left;
- root -> left = temp;
-
- temp -> height = max(getHeight(temp -> left), getHeight(temp -> right)) + 1;
- root -> height = max(getHeight(root -> left), getHeight(root -> right)) + 1;
- }
-
- template <typename T>
- void avlTree<T>::lrRotation(avlTreeNode<T>* &root){
- //先进行左旋转,在进行右旋转
- rrRotation(root -> left);
- llRotation(root);
- }
-
- template <typename T>
- void avlTree<T>::rlRotation(avlTreeNode<T>* &root){
- //先进行左旋转,在进行右旋转
- llRotation(root -> right);
- rrRotation(root);
- }
-
- template <typename T>
- void avlTree<T>::addValue(avlTreeNode<T>* &root, T val){
- if(root == NULL){//根节点是NULL
- root = new avlTreeNode<T>(val, NULL, NULL);
- }else if(root -> data > val){//插入到左子树
- addValue(root -> left, val);
- if(getHeight(root -> left) - getHeight(root -> right) == 2){
- if(root -> left -> data > val){
- llRotation(root);
- }else{
- lrRotation(root);
- }
- }
- }else if(root -> data < val){//插入到右子树
- addValue(root -> right, val);
- if(getHeight(root -> left) - getHeight(root -> right) == -2){
- if(root -> right -> data > val){
- rlRotation(root);
- }else{
- rrRotation(root);
- }
- }
- }else{
- cout << "平衡树中已有该结点" <<endl;
- }
-
- root -> height = getHeight(root -> left) > getHeight(root -> right) ? getHeight(root -> left) + 1:getHeight(root -> right) + 1;
- }
-
- template <typename T>
- void avlTree<T>::creatAvlTree(){
- T val;
- cin >> val;
-
- while(val != '#'){
- addValue(root, val);
- cin >> val;
- }
- }
-
- template <typename T>
- void avlTree<T>::delValue(avlTreeNode<T>* &root, T val){
- if(root == NULL)//树中没有值为val的节点
- return;
- if(root -> data == val){
- if(root -> left != NULL && root -> right != NULL){
- //左子树高度大,删除左子树中值最大的结点,将其赋给根结点
- if(getHeight(root -> left) > getHeight(root -> right)){
- root -> data = getMax(root -> left) -> data;
- delValue(root -> left, root -> data);
- }else{//右子树高度更大,删除右子树中值最小的结点,将其赋给根结点
- root -> data = getMin(root -> right) -> data;
- delValue(root -> right, root -> data);
- }
- }else{//左右子树有一个不为空,直接用需要删除的结点的子结点替换即可
- avlTreeNode<T>* temp = root;
- root = root -> left == NULL ? root -> right: root -> left;
- delete temp;
- }
-
- }else if(root -> data < val){//在root的右子树删除val
- delValue(root -> right, val);
-
- if(getHeight(root -> right) - getHeight(root -> left) == -2){//需要进行调整
- if(getHeight(root -> left -> left) > getHeight(root -> left -> right)){
- llRotation(root);
- }else{
- lrRotation(root);
- }
-
- }else{//不需要调整
- root -> height = max(getHeight(root -> right), getHeight(root -> left)) + 1;
- }
-
- }else if(root -> data > val){//在root的左子树删除val
- delValue(root -> left, val);
-
- if(getHeight(root -> right) - getHeight(root -> left) == 2)
- {//需要进行调整
- if(getHeight(root -> right -> left) > getHeight(root -> right -> right)){
- rlRotation(root);
- }else{
- rrRotation(root);
- }
- }else{//不需要调整
- root -> height = max(getHeight(root -> right), getHeight(root -> left)) + 1;
- }
- }
- }
-
- template <typename T>
- avlTreeNode<T>* avlTree<T>::getMin(avlTreeNode<T>* root) const{//找到以root为根节点的树中最小的节点
- if(root == NULL)
- return NULL;
- while(root -> left != NULL){
- root = root -> left;
- }
- return root;
- }
-
- template <typename T>
- avlTreeNode<T>* avlTree<T>::getMax(avlTreeNode<T>* root) const{//找到以root为根节点的树中最大的节点
- if(root == NULL)
- return NULL;
- while(root -> right != NULL){
- root = root -> right;
- }
- return root;
- }
-
- template <typename T>
- void avlTree<T>::printAvlTreeOfPre() const{
- if(root == NULL)
- return;
- stack <avlTreeNode<T>*> stc;
- stc.push(root);
-
- while(!stc.empty()){
- avlTreeNode<T>* temp = stc.top();
- stc.pop();
- cout << temp -> data << " ";
-
- if(temp -> right != NULL){
- stc.push(temp -> right);
- }
-
- if(temp -> left != NULL){
- stc.push(temp -> left);
- }
- }
- }
-
- template <typename T>
- void avlTree<T>::printAvlTreeOfIn() const{
- if(root == NULL)
- return;
- stack <avlTreeNode<T>*> stc;
- avlTreeNode<T>* temp = root;
- while(!stc.empty() || temp != NULL){
- if(temp != NULL){
- stc.push(temp);
- temp = temp -> left;
- }else{
- temp = stc.top();
- stc.pop();
- cout << temp -> data << " ";
- temp = temp -> right;
- }
- }
- }
-
- int main(){
- avlTree<char>* tree = new avlTree<char>;
- tree -> creatAvlTree();
- cout<<endl<<"前序遍历结果:"<<endl;
- tree -> printAvlTreeOfPre();
- cout<<endl<<"中序遍历结果:"<<endl;
- tree -> printAvlTreeOfIn();
- cout<<endl;
- tree -> delValue(tree -> getRoot(), 'a');
- cout<<endl<<"删除结点a之后的前序遍历结果:"<<endl;
- tree -> printAvlTreeOfPre();
- cout<<endl<<"删除结点a之后的中序遍历结果:"<<endl;
- tree -> printAvlTreeOfIn();
- cout<<endl;
- return 0;
- }
测试结果如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。