AVL树插入删除

写了好久,感觉插入和删除麻烦些,插入也就4种情况,但只要写两个函数,左左和右右的,左右的情况是以根节点的左子树为头进行一次右右旋转,使它变成左左的情况,再左左旋转下就下,右左的也一样;

另外就是删除,先是判断要删除的节点右儿子是否为空,是空,直接删,否则找到它最左边的儿子来替代它,然后就是高度的更新,重新的旋转。。。

哎,真实花了我好长时间,不过终于写完了。大致感觉没啥问题了吧,有的话以后再改吧。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <cmath>

using namespace std;

typedef struct AvlNode              // AVL树的节点
{
    int data;
    struct AvlNode *left;           // 左孩子
    struct AvlNode *right;          // 右孩子
    int Height;
}*Position,*AvlTree;

AvlTree MakeEmpty(AvlTree T);
Position Find(int x,AvlTree T);
Position Find_right(AvlTree T);
Position FindMax(AvlTree T);

int Search(AvlTree T);
AvlTree  Insert(int x,AvlTree T);
AvlTree  Delete(int  x,AvlTree T);

AvlTree left_left(AvlTree k1);
AvlTree right_right(AvlTree k1);
AvlTree left_right(AvlTree k1);
AvlTree right_left(AvlTree k1);
AvlTree Printf_tree(AvlTree T);
AvlTree balance(AvlTree T);

int main()
{
    AvlTree T =NULL;
    getchar();
   T=Insert(2,T);
   T= Insert(7,T);
     //Printf_tree(T);
    T= Insert(5,T);
    //Printf_tree(T);
    T=Insert(11,T);
    T=Insert(9,T);
    T=Insert(10,T);
    T=Insert(100,T);
    T=Insert(14,T);
    T=Insert(20,T);
   Printf_tree(T);
  T = Delete(5,T);
   printf("\n");
   Printf_tree(T);
    printf("\n");
    T = Delete(2,T);
     Printf_tree(T);
    getchar();
    return 0;
}
AvlTree MakeEmpty(AvlTree T)
{
    if(T!=NULL)
    {
        MakeEmpty(T->left);
        MakeEmpty(T->right);
        free(T);
    }
    return NULL;
}

int height(AvlTree T)
{
    if(T==NULL)return -1;
    else return T->Height;
}

//向树中插入数据
AvlTree Insert(int x,AvlTree T)
{
    if(T==NULL)
    {
        T = (AvlTree)malloc(sizeof(struct AvlNode));
        T->data = x;
        T->Height = 0;
        T->left = NULL;
        T->right = NULL;
    }
    //如果插入元素小于当前元素
    else if(x<T->data)
    {
        T->left = Insert(x,T->left);
        if(height(T->left)-height(T->right)==2)
        {
            if(x<T->left->data)
                T = left_left(T);
            else
                T = left_right(T);
        }

    }
    else if(x>T->data)
    {
        T->right = Insert(x,T->right);
        if(height(T->right)-height(T->left)==2)
        {
            if(x<T->right->data)
                T = right_left(T);
            else
                T = right_right(T);
        }
    }
    T->Height = max(height(T->left),height(T->right))+1;
    return T;
}

//左左旋转
AvlTree left_left(AvlTree k1)
{
    //if(height(k1->left)-height(k1->right)<2)return k1;
    AvlTree k2 = k1->left;
    k1->left = k2->right;
    k2->right = k1;
   k1->Height = max(height(k1->left),height(k1->right))+1;
    k2->Height = max(height(k2->left),height(k2->right))+1;
    return k2;
}

//右右旋转

AvlTree right_right(AvlTree k1)
{
    //if(height(k1->right)-height(k1->left)<2)return k1;
    AvlTree k2 = k1->right;
    k1->right = k2->left;
    k2->left = k1;
    k1->Height = max(height(k1->left),height(k1->right))+1;
    k2->Height = max(height(k2->left),height(k2->right))+1;
    return k2;
}

//左右旋转

AvlTree left_right(AvlTree k1)
{
    k1->left = right_right(k1->left);
    return left_left(k1);
}

//右左旋转

AvlTree right_left(AvlTree k1)
{
    k1->right = left_left(k1->right);
    return right_right(k1);
}

AvlTree Printf_tree(AvlTree T)
{
    if(T==NULL)return NULL;
    else
    {
        printf("父亲节点是:%d ",T->data);
        printf("左儿子是: ");
        if(T->left==NULL)printf("NULL");
       else printf("%d",T->left->data);
       printf("右儿子是:");
       if(T->right==NULL)printf("NULL");
       else printf("%d",T->right->data);
       printf(" 高度是:%d\n",height(T));
    }
    Printf_tree(T->left);
    Printf_tree(T->right);
}

AvlTree Delete(int x,AvlTree T)
{
    if(T==NULL)return NULL;
    else
    {
        if(T->data==x)
        {
            if(T->right==NULL)
            {
                AvlTree tem = T;
                T = T->left;
                free(tem);
            }
            else
            {
                AvlTree tem = T->right;
                while(tem->left!=NULL)
                {
                    tem = tem->left;
                }
                T->data = tem->data;
                //free(tem);
                //tem=NULL;
                T->right = Delete(T->data,T->right);
                T->Height = max(height(T->left),height(T->right))+1;
            }
            return T;
        }
        else if(x>T->data)
        {
            T->right = Delete(x,T->right);
        }
        else if(x<T->data)
        {
            T->left = Delete(x,T->left);
        }

        //删除后判断是否平衡,不平衡则需旋转
        T->Height = max(height(T->left),height(T->right))+1;
        if(T->left!=NULL)
        {
            T->left = balance(T->left);
        }
        if(T->right!=NULL)
        {
            T->right = balance(T->right);
        }
        if(T!=NULL)
        {
            T = balance(T);
        }
        return T;
    }
}

AvlTree balance(AvlTree T)
{
    if(height(T->left)-height(T->right)==2)
    {
        if(height(T->left->left)>height(T->left->right))
        {
            T = left_left(T);
        }
        else
        {
            T = left_right(T);
        }
    }
    else if(height(T->right)-height(T->left)==2)
    {
        if(height(T->right)-height(T->left))
        {
            T = right_right(T);
        }
        else
        {
            T = right_left(T);
        }
    }
    else
    {
        return T;
    }
}
时间: 2024-11-05 20:46:56

AVL树插入删除的相关文章

AVL树插入和删除

一.AVL树简介 AVL树是一种平衡的二叉查找树. 平衡二叉树(AVL 树)是一棵空树,或者是具有下列性质的二叉排序树:    1它的左子树和右子树都是平衡二叉树,    2且左子树和右子树高度之差的绝对值不超过 1. 定义平衡因子(BF)为该结点左子树的高度减去右子树的高度所得的高度差:AVL 树任一结点平衡因子只能取-1,0,1: 二.AVL树插入 插入:先查找被插入元素,如果存在,则不操作:如果不存在,则插入. 插入后就是调整和选择的问题. 我们先看一下我们会面临怎么样的问题: 离插入点最

看数据结构写代码(57) AVL树的删除

上一节 已经说了 AVL树的插入 操作,可是 只有 插入,没有删除,怎么能叫 动态 查找表呢. 呵呵,博主 赶紧 去 研究了一番.下面 是成果: AVL树的删除 大致 分为 两大块: 1. 查找节点 并 删除 2. 保持 删除 后 平衡因子的 影响 1. 首先 找到 这个 节点,如果 节点 不存在,直接 退出 函数 if (*tree == NULL){//没找到 return false; } 2.如果 存在,分为 四种情况:(根 二叉 排序树的 删除 类似) 1.节点 为 叶子 节点,直接

AVL树之删除算法

1.AVL树删除 思路:   (1).首先找到要删除的结点:没找到,直接false返回退出即可:     (2).将其转化为只有一个分支的结点,前面的路径都要入栈,     (3).其父节点(parent)的平衡因子(根据父的左/右=p(要删除的结点),修改父的bf),有几种情况,i>父节点的bf=1/-1,代表原先有两个结点,现在剩下一个了,直接退出循环,不用再往上寻找更改bf了:ii>父节点的bf=0:代表此时的往上更改爷爷结点(在此出栈即可,栈中保存了路径信息)的bf,看情况(bf=2/

AVL树插入(Python实现)

建立AVL树 1 class AVLNode(object): 2 def __init__(self,data): 3 self.data = data 4 self.lchild = None 5 self.rchild = None 6 self.parent = None 7 self.bf = 0 8 9 class AVLTree(object) 10 def __init__(self,li=None) 11 self.root = None 12 if li: 13 for va

AVL树插入操作InsertAVL的实现

AVL树是非常重要的一种数据结构,这里实现了在AVL树中的插入操作,包括插入后整个树的自平衡. 这里有几点值得注意的地方: 1).左旋L_Rotate与右旋R_Rotate操作: 这两个操作传递进来的参数是以TreeNode*&的形式传递进来的,也就是说传递的是指针的引用,效果等价于传递二级指针 如果不加入&,则在函数内部更改的是形参的指向,因为实际上函数调用时,如果不采用引用传递,则会构造一个与原T指向同一个地方的临时变量指针,在X_Rotate的内部也是对这个临时变量进行操作,等到返回

AVL树非递归插入删除思路

AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多次树旋转来重新平衡这个树.AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文<An algorithm for the organization of information>中发表了它. 节点的平衡因子是它的左子树的高度减去它的右子树的

AVL树的插入与删除

AVL 树要在插入和删除结点后保持平衡,旋转操作必不可少.关键是理解什么时候应该左旋.右旋和双旋.在Youtube上看到一位老师的视频对这个概念讲解得非常清楚,再结合算法书和网络的博文,记录如下. 1.1 AVL 的旋转 一棵AVL树是其每个节点的左子树和右子树的高度差最多为1的二叉查找树(空树高度定义为-1).AVL树插入和删除时都可能破坏AVL的特性,可以通过对树进行修正来保证特性,修正方法称为旋转. 下面以4个插入操作为例,说明不同旋转对应的场景. 1.1.1 LL-R 插入结点为6,沿着

AVL树的插入和删除

一.AVL 树 在计算机科学中,AVL树是最早被发明的自平衡二叉查找树.在AVL树中,任一节点对应的两棵子树的最大高度差为 1,因此它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度都是 O(log(n)).插入和删除元素的操作则可能需要借由一次或多次树旋转,以实现树的重新平衡. 节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反).带有平衡因子 1.0 或 -1 的节点被认为是平衡的.带有平衡因子 -2 或 2 的节点被认为是不平衡的,并需要重新平衡这个树.平衡因

AVL树原理及实现(C语言实现以及Java语言实现)

欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好是按照从小到大的顺序或者从大到小的顺序插入的,那么搜索二叉树就对退化成链表,这个时候查找,插入和删除的时间都会上升到O(n),而这对于海量数据而言,是我们无法忍受的.即使是一颗由完全随机的数据构造成的搜索二叉树,从统计角度去分析,在进行若甘次的插入和删除操作,这个搜索二叉树的高度也不能令人满意.这个