AVL平衡二叉树——常用标准函数代码

AVL平衡二叉树——常用标准函数代码

AVL树仍然是一颗二叉查找树,只是在其基础上增加了**“平衡”**的要求。

由于需要对每个节点都得到平衡因子,因此需要在树的结构中加入height变量,用来记录以当前节点为根节点的子树的高度。

结构体如下:
struct node {
    int v, height;
    node *lchild, *rchild;
};
新建结点:
node* newNode(int v) {
    node* Node = new node;
    Node->v = v;
    Node->height = 1;
    Node->lchild = Node->rchild = NULL;
    return Node;
}
获取某结点(root)的高度(height):
int getHeight(node* root) {
	if(root == NULL) return 0;
	return root->height;
}
计算某结点(root)的平衡因子:
int getBalanceFactor(node* root) {
    //左子树高度减右子树高度
    return getHeight(root->lchild) - getHeight(root->rchild);
}
更新某结点(root)的高度(height):
void updateHeight(node* root) {
	//max(左孩子的height,右孩子的height) + 1
	root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}
查找操作

查找AVL树中数据域为x的结点:

//首次传入的root为根节点指针,x为欲查找的元素值
void search(node* root, int x) {
    if(root == NULL) {
        printf("查找失败\n");
        return;
    }
    if(x == root->data) {
        printf("%d查找成功\n", root->data);
    } else if (x < root->data) { //如果x比当前节点小
        search(root->lchild, x); //递归左子树查找
    } else if (x >= root->data) { //如果x比当前结点大
        search(root->rchild, x); //递归右子树查找
    }
}
平衡调整

左旋

void L(node* &root) {
	//root指向结点A,temp指向结点B
	node* temp = root->rchild;
	root->rchild = temp->lchild;
	temp->lchild = root;
	updateHeight(root);	//更新A结点高度
	updateHeight(temp); //更新B结点高度
	root = temp;
}

右旋

void R(node* &root) {
	//root指向结点B,temp指向结点A
	node* temp = root->lchild;
	root->lchild = temp->rchild;
	temp->rchild = root;
	updateHeight(root);	//更新B结点高度
	updateHeight(temp); //更新A结点高度
	root = temp;
}

AVL树插入情况汇总(BF表示平衡因子)

树型判定条件调整方法
LLBF(root) = 2, BF(root->lchild) = 1对root进行右旋
LRBF(root) = 2, BF(root->lchild) = -1先对root->lchild进行左旋,再对root进行右旋
RRBF(root) = -2, BF(root->lchild) = -1对root进行左旋
RLBF(root) = -2, BF(root->lchild) = 1先对root->rchild进行右旋,再对root进行左旋
插入操作(难点)

AVL树的插入代码是在二叉查找树的插入代码的基础上增加平衡操作,因此需要在每个insert函数之后更新当前子树的高度,并在这之后根据树型是LL型、LR型、RR型、RL型之一来进行平衡操作。

//向AVL树插入权值为v的结点
void insert(node* &root, int v) {
    if(root == NULL) {
        root = newNode(v);
        return;
    }
    if(v < root->v) { //v比根节点的权值小
        insert(root->lchild, v); //往左子树插入
        updateHeight(root); //更新树高
        if(getBalanceFactor(root) == 2) { //平衡被破坏,需要调平
            if(getBalanceFactor(root->lchild) == 1) { //LL型
                R(root);
            } else if(getBalanceFactor(root->lchild) == -1) { //LR型
                L(root->lchild);
                R(root);
            }
        }
    } else { //v比根节点的权值大
        insert(root->rchild, v); //往右子树插入
        updateHeight(root); //更新树高
        if(getBalanceFactor(root) == -2) { //平衡被破坏,需要调平
            if(getBalanceFactor(root->rchild) == -1) { //RR型
                L(root);
            } else if(getBalanceFactor(root->rchild) == 1) { //RL型
                R(root->rchild);
                L(root);
            }
        }
    }
}

AVL树的建立

有了上面的基本操作,AVL树的建立就变得非常简单了,只需要依次插入n个结点即可。

node* Create(int data[], int n) {
    node* root = NULL; //新建空的根节点
    for(int i = 0; i < n; i++) {
        insert(root, data[i])
    }
    return root; //返回根结点
}

一起加油!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
http://www.400gb.com/u/256394 译者序 前言 致谢 第1章 绪论  1.1 评估算法  1.2 修改算法   1.2.1 主要的优化:I/O   1.2.2 主要的优化:函数调用  1.3 资源和参考资料 第2章 基本数据结构  2.1 链表   2.1.1 双向链表   2.1.2 链表的其他特征  2.2 栈和队列   2.2.1 栈的特征   2.2.2 队列的特征 第3章 散列  3.1 散列的概念  3.2 散列函数  3.3 冲突解决方法   3.3.1 线性再散列法   3.3.2 非线性再散列法   3.3.3 外部拉链法  3.4 性能问题  3.5 资源和参考资料 第4章 查找  4.1 查找的特征   4.1.1 准备时间   4.1.2 运行时间     4.1.3 回溯的需要  4.2 蛮力查找  4.3 Boyer Moore查找   4.3.1 启发式方法#1:跳过字符   4.3.2 启发式方法#2:重复模式  4.4 多字符串查找  4.5 用于正则表达式的字符串查找:grep  4.6 近似字符串匹配技术  4.7 语音比较:Soundex算法  4.8 Metaphone:现代的Soundex  4.9 选择技术  4.10 资源和参考资料   4.10.1 通用参考资料   4.10.2 Boyer Moore   4.10.3 多字符串查找   4.10.4 正则表达式查找   4.10.5 近似字符串匹配   4.10.6 Soundex算法和Metaphone算法 第5章 排序  5.1 排序的基本特征   5.1.1 稳定性   5.1.2 对哨兵的需求   5.1.3 对链表进行排序的能力   5.1.4 输入的阶的相关性   5.1.5 对额外存储空间的需求   5.1.6 内部排序技术与外部排序技术  5.2 排序模型   5.2.1 冒泡排序   5.2.2 插入排序   5.2.3 希尔排序   5.2.4 快速排序   5.2.5 堆排序  5.3 对链表进行插入排序  5.4 对链表进行快速排序  5.5 对多个键进行排序——不稳定排序的修正方法  5.6 网络排序  5.7 小结:选择一种排序算法  5.8 资源和参考资料 第6章 树  6.1 二叉树   6.1.1 树查找   6.1.2 节点插入   6.1.3 节点删除   6.1.4 二叉查找树的性能   6.1.5 AVL树  6.2 红黑树  6.3 伸展树  6.4 B树   6.4.1 保持B树平衡   6.4.2 实现B树算法   6.4.3 B树实现的代码  6.5 可以看见森林吗  6.6 资源和参考资料 第7章 日期和时间  7.1 日期例程的库  7.2 时间例程  7.3 用于日期和时间数据的格式  7.4 最后的提醒  7.5 资源和参考资料 第8章 任意精度的算术  8.1 构建计算器8.2表示数字  8.3 计算  8.4 加法  8.5 减法  8.6 乘法  8.7 除法  8.8 关于计算器要注意的最后几点  8.9 用于计算平方根的牛顿算法  8.10 分期付款表  8.11 资源和参考资料 第9章 数据压缩  9.1 行程编码  9.2 霍夫曼压缩   9.2.1 代码   9.2.2 其他问题  9.3 滑动窗口压缩  9.4 基于字典的压缩(LZW)   9.4.1 LZW算法的伪代码   9.4.2 LZW压缩的实现   9.4.3 填满字典  9.5 使用哪种压缩方法  9.6 资源和参考资料 第10章 数据完整性和验证  10.1 简单的校验和  10.2 加权校验和  10.3 循环冗余校验   10.3.1 CRC CCITT   10.3.2 CRC 16   10.3.3 CRC 32   10.4 资源和参考资料
平衡二叉树AVL树)是一种自平衡的二叉搜索树,它的左右子树的高度差不超过1。下面是一个非递归实现的平衡二叉树的C++代码示例: ```cpp #include <iostream> #include <stack> using namespace std; struct TreeNode { int val; int height; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), height(1), left(NULL), right(NULL) {} }; int getHeight(TreeNode* node) { if (node == NULL) { return 0; } return node->height; } int getBalanceFactor(TreeNode* node) { if (node == NULL) { return 0; } return getHeight(node->left) - getHeight(node->right); } TreeNode* rotateLeft(TreeNode* node) { TreeNode* newRoot = node->right; node->right = newRoot->left; newRoot->left = node; node->height = max(getHeight(node->left), getHeight(node->right)) + 1; newRoot->height = max(getHeight(newRoot->left), getHeight(newRoot->right)) + 1; return newRoot; } TreeNode* rotateRight(TreeNode* node) { TreeNode* newRoot = node->left; node->left = newRoot->right; newRoot->right = node; node->height = max(getHeight(node->left), getHeight(node->right)) + 1; newRoot->height = max(getHeight(newRoot->left), getHeight(newRoot->right)) + 1; return newRoot; } TreeNode* insert(TreeNode* root, int val) { if (root == NULL) { return new TreeNode(val); } if (val < root->val) { root->left = insert(root->left, val); } else if (val > root->val) { root->right = insert(root->right, val); } else { return root; // 不允许插入重复的节点 } root->height = max(getHeight(root->left), getHeight(root->right)) + 1; int balanceFactor = getBalanceFactor(root); if (balanceFactor > 1 && val < root->left->val) { return rotateRight(root); } if (balanceFactor < -1 && val > root->right->val) { return rotateLeft(root); } if (balanceFactor > 1 && val > root->left->val) { root->left = rotateLeft(root->left); return rotateRight(root); } if (balanceFactor < -1 && val < root->right->val) { root->right = rotateRight(root->right); return rotateLeft(root); } return root; } void inorderTraversal(TreeNode* root) { if (root == NULL) { return; } stack<TreeNode*> s; TreeNode* curr = root; while (curr != NULL || !s.empty()) { while (curr != NULL) { s.push(curr); curr = curr->left; } curr = s.top(); s.pop(); cout << curr->val << " "; curr = curr->right; } } int main() { TreeNode* root = NULL; int arr[] = {3, 2, 4, 5, 6, 1}; int n = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i < n; i++) { root = insert(root, arr[i]); } cout << "Inorder traversal of the AVL tree: "; inorderTraversal(root); return 0; } ``` 这段代码实现了平衡二叉树的插入操作,并通过中序遍历打印出了平衡后的树节点值。你可以根据需要进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值