二查平衡树的插入与删除(四种旋转)

// AVL.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;
//最近需要面试,写以下二查平衡树的插入,删除代码。加深印象,其中的难点是旋转问题。
//有不正确的地方,恳请批评指正!

typedef struct node //结点的数据结构
{
    int value;
    node* left;
    node* right;
    int height;
    node(int x):value(x),left(NULL),right(NULL),height(1){}
}node;

int height(node* p)   //返回结点的高度
{
     if(p == NULL)
        return 0;
     else
         return p->height;
}

//左左情况下的调整
void SingleRoateLeft(node* &k2)
{
    node* 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),height(k1->right))+1;
    k2 = k1;
}

//右右情况下的调整
void SingleRoateRight(node* &k2)
{
    node* k1 = k2->right;
    k2->right = k1->left;
    k1->left = k2;
    k2->height = max(height(k2->left),height(k2->right))+1;
    k1->height = max(height(k1->left),height(k1->right))+1;
    k2 = k1;
}

//左右情况下的调整
void DoubleRoateLR(node* &k3)
{
    SingleRoateRight(k3->left);
    SingleRoateLeft(k3);
}

//右左情况下的调整
void DoubleRoateRL(node* &k3)
{
    SingleRoateLeft(k3->right);
    SingleRoateRight(k3);
}

//在以p为根结点的树上,插入结点x
void InsertNode(node* &p, int x)
{
    if(p == NULL)  //如果是空树
    {
        p = new node(x); 
        return ;
    }
    if(x < p->value)  //在左子树中插入
    {
        InsertNode(p->left,x);
        //插入结点完成后,需要检查树是否平衡
        if(2 == height(p->left) - height(p->right))
        {
            if(p->left->value > x)//左左
            {
                SingleRoateLeft(p);
            }
            else//左右
            {
                DoubleRoateLR(p);
            }
        }
    }
    else if(x > p->value) //在右子树上插入结点
    {
        InsertNode(p->right,x);
        //插入结点完成后,需要检查树是否平衡
        if(2 == height(p->right) - height(p->left))
        {
            if(p->right->value < x) //右右
            {
                SingleRoateRight(p);
            }
            else//右左
            {
                DoubleRoateRL(p);
            }
        }
    }
    else // x== p->value 不做处理
    {
        return;
    }
    p->height = max(height(p->left),height(p->right))+1;
}

//在以p为根节点的树上,删除结点,元素值为x
void DeleteNode(node* &p, int x)
{
    if(p == NULL)//p为空树
        return ;
    if(x < p->value)//在左子树上删除
    {
        DeleteNode(p->left,x);
        //删除完后,需要检查树的平衡性
        if(2 == height(p->right) - height(p->left))
        {
            if(p->right->left && height(p->right->left) > height(p->right->right))
                DoubleRoateRL(p);
            else
                SingleRoateRight(p);
        }
    }
    else if(x > p->value)//在右子树上删除
    {
        DeleteNode(p->right,x);
        //删除完后,需要检查树的平衡性
        if(2 == height(p->left)-height(p->right))
        {
            if(p->left->right && height(p->left->right) > height(p->left->left))
                DoubleRoateLR(p);
            else
                SingleRoateLeft(p);
        }
    }
    else //找到了需要删除的结点,x == p->value
    {
        if(p->left && p->right) //有两个孩子,需要找后继结点,原理与二叉查找树一样
        {
            node* temp = p->right;
            //找p的后继结点
            while (temp->left)
            {
                temp = temp->left;
            }
            p->value = temp->value;//元素值的替换
            DeleteNode(p->right,temp->value);//删除后继结点
            if(2 == height(p->left)-height(p->right)) //删除完后,需要检查树的平衡
            {
                if(p->left->right && height(p->left->right) > height(p->left->left))
                    DoubleRoateLR(p);
                else
                    SingleRoateLeft(p);
            }
        }
        else//只有一个孩子或没有孩子,只需把指针关系调整下即可
        {
            node* temp = p;
            if(p->left == NULL)
                p = p->right;
            else if(p->right == NULL)
                p = p->left;
            delete temp;
            temp = NULL;
        }
    }
    if(p == NULL)
        return;
    p->height = max(height(p->left),height(p->right))+1;
}
int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值