C++ AVL树(高度平衡的二叉搜索树)

本文介绍了C++实现AVL树的思路,包括创建、插入和删除操作。插入时,先寻找插入位置,然后插入并进行平衡调整,通过旋转恢复平衡。删除操作涉及查找删除节点,若节点有两个子节点则需找到中序遍历的直接前驱或后继节点替换,然后更新平衡因子和进行旋转调整。提供了实现程序的头文件和主文件。
摘要由CSDN通过智能技术生成

一、思路

   1.创建AVL树:

      每次输入一个数num,然后用Insert()函数,将num插入到AVL树中。

// 创建AVL平衡树
template <class T>
void AVLTree<T>::CreateAVLTree() {
    T num;
    
    cout << "请输入数(以-1结束输入)建立平衡二叉树:" << endl;
    while(cin >> num && num != -1)
        Insert(num); // 插入到树中
}

2.插入值x:

 (1)寻找插入的位置:如果AVL树已经存在该x值,则不插入。如果x小于当前结点的值,则往左子树中找插入位置;否则,往右子树找插入位置。

// 1.寻找插入位置
    while(p != NULL) { // 树不为空
        if(x == p->data) // 已经存在该值,不用再插入
            return false;
        pre = p; // 保存当前结点
        st.push(pre); // 用栈记忆查找路径
        if(x < p->data) // 要插入的值小于当前结点的值,往左子树继续查找
            p = p->left;
        else // x大于当前结点的值
            p = p->right; // 往右子树查找
    }

(2)把x插入到AVL平衡树中:如果x小于父结点的值,则插入到父结点的左孩子位置;否则, 插入到父结点的右孩子上。

// 2.找到了准备插入的位置,把x插入到AVL平衡树中
    p = new AVLNode<T>(); // 创建新结点
    p->data = x; // 存储要插入的值
    p->bf = 0; // 新结点,平衡因子为0
    p->left = p->right = NULL;
    if(p == NULL) {
        cerr << "存储空间分配失败!" << endl;
        exit(1);
    }
    if(pre == NULL) { // 空树,新结点成为根结点
        root = p;
        return true;
    }
    if(x < pre->data) // 插入到左子树
        pre->left = p;
    else
        pre->right = p; // 插入到右子树

(3)重新平衡化AVL树:因为插入的新结点,可能导致AVL树平衡被破坏。

         从插入的新结点的父结点开始往根结点调整。如果当前结点是父结点的左孩子,则父结点的平衡因子要减1,如果当前结点是父结点的右孩子,则父结点的平衡因子要加1

         然后,通过父结点parent的平衡因子来决定是否需要平衡化旋转:

         A. 父结点parent的平衡因子为0说明刚才是在parent的较矮的子树上插入了新结点,父结点处平衡,且高度没有增减。此时从parent到根的路径上各结点为根的子树高度不变,从而各个结点的平衡因子不变,可以结束重新平衡化的处理。

         B.父结点parent的平衡因子的绝对值|bf|=1说明插入前parent结点的平衡因子为0,插入新结点后,以parent为根的子树没有失去平衡,不需要平衡化旋转。但该子树的高度增加,还需从结点parent向根的方向回溯,继续考查结点parent的父结点的平衡状态。

         C.父结点parent的平衡因子的绝对值|bf|=2说明新结点在较高的子树上插入,造成了不平衡,需要做平衡化旋转。旋转要分情况讨论。旋转后以parent为根的子树高度降低,因此无需继续向上层回溯。

// 3.重新平衡化AVL树
    while(st.empty() == false) { // 栈不空
        pre = st.top(); // 取栈顶元素
        st.pop();
        if(p == pre->left) // 如果是左孩子结点,则父结点平衡因子减1
            pre->bf--; // 调整父结点的平衡因子
        else
            pre->bf++; // 如果是右孩子结点,则父结点平衡因子加1
        
        if(pre->bf == 0) // 第1种情况,平衡退出
            break;
        else if(pre->bf == 1 || pre->bf == -1) // 第2种情况,|bf|&
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值