13、二叉搜索树-AVL树
来源:互联网 发布:一句话经典 知乎 编辑:程序博客网 时间:2024/06/03 19:36
1、树的组织方式:左节点小于根节点,右节点大于根节点。平衡二叉树最坏情况log2 (n)。顺序排列只有单支最坏情况为n。可以采取随机插入等方式解决此问题,其中最好的方法就是 二叉搜索树实现AVL树。
2、AVL树:每个节点额外保存一个平衡因子,值为右子树高度减去左子树高度。插入节点时,AVL树需要自我调整保持所有平衡因子值为-1(左倾斜)、0、+1(右倾斜)。根节点的平衡因子代表整个树的平衡性。
3、实际上红黑树的统计性比AVL树更好。
4、几种其他树:
(1)K叉树:每个节点有多条分支
(2)红黑树:节点有颜色属性,红、黑
(3)Trie树:用来查找变长字符串组合
(4)B、B+、B*树:数据库系统使用来提高访问辅助存储设备上的数据。一般通过优化手段使节点大小和辅助存储设备的块大小保持一致。
5、AVL树旋转:旋转分为LL旋转、LR旋转、RR旋转、RL旋转。任何平衡因子变为+-2时,重新向下平衡。
总结为两步:
(1)把长分支转换到最左侧,或最右侧
(2)从儿子节点往短的那边折
图中最底层的节点也可以是红圈的位置,它影响平衡调整
6、AVL树函数实现
(1)数据结构
//AVL树节点,BIT_TREE_NODE树节点的*data指向这个节点typedef struct AvlNode_{ void *data;//节点存储的具体内容 int hidden;//0代表该节点不在树中 int factor;//平衡因子,表示该节点子树左右的倾斜程度}AvlNode;
(2)LL旋转和LR旋转
//调整tree树,node为返回变换后的root点,一般每插一个节点都会调整一次,不会出现超过+-2的情况//LL旋转:节点*node的左叶的左叶重,*node -2,只有root节点和其左叶节点要变//root节点的左叶变为,左叶的右叶;左叶变为root,其右叶为原root//LR:节点*node的左叶的右叶重,*node -2,root节点、左子叶、左左子叶的右子叶(孙子叶)要变static void rotate_left(BisTree *tree, BiTreeNode **node){ BiTreeNode *left, *grandchild; left = bittree_left(*node); //LL旋转 if(((AvlNode *)bittree_left(left))->factor == AVL_LFT_HEAVY) { bittree_left(*node) = bittree_right(left); bittree_right(left) = *node; ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; ((AvlNode *)bittree_data(left))->factor = AVL_BALANCED; *node = left; } //LR旋转 else { grandchild = bittree_right(left); //左叶的右子树为,孙子的左子树 bittree_right(left) = bittree_left(grandchild); //孙子的左子树为,原左叶 bittree_left(grandchild) = left; //root节点的左叶为,孙子的右叶 bittree_left(*node) =bittree_right(grandchild); //孙子右为,原root bittree_right(grandchild) = *node; //调整权重,孙子肯定平衡,孙子之前的左偏、右偏决定,父和左节点的平衡性 switch(((AvlNode *)bittree_left(grandchild))->factor) { case AVL_LFT_HEAVY: ((AvlNode *)bittree_data(*node))->factor = AVL_REG_HEAVY; ((AvlNode *)bittree_data(left))->factor = AVL_BALANCED; break; case AVL_REG_HEAVY: ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; ((AvlNode *)bittree_data(left))->factor = AVL_LFT_HEAVY; break; case AVL_BALANCED: ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; ((AvlNode *)bittree_data(left))->factor = AVL_BALANCED; break; } ((AvlNode *)bittree_data(grandchild))->factor = AVL_BALANCED; *node = grandchild; }}
(3)RR、RL旋转
static void rotate_right(BiTreeNode **node){ BiTreeNode *right, *grandchild; right = bittree_right(*node); if(((AvlNode *)bittree_right(right))->factor == AVL_REG_HEAVY) { bittree_right(*node) = bittree_left(right); bittree_left(right) = *node; ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; ((AvlNode *)bittree_data(right))->factor = AVL_BALANCED; *node = right; } else { grandchild = bittree_left(right); bittree_left(right) = bittree_right(grandchild); bittree_right(grandchild) = right; bittree_right(*node) =bittree_left(grandchild); bittree_left(grandchild) = *node; switch(((AvlNode *)bittree_left(grandchild))->factor) { case AVL_LFT_HEAVY: ((AvlNode *)bittree_data(*node))->factor = AVL_REG_HEAVY; ((AvlNode *)bittree_data(right))->factor = AVL_BALANCED; break; case AVL_REG_HEAVY: ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; ((AvlNode *)bittree_data(right))->factor = AVL_LFT_HEAVY; break; case AVL_BALANCED: ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; ((AvlNode *)bittree_data(right))->factor = AVL_BALANCED; break; } ((AvlNode *)bittree_data(grandchild))->factor = AVL_BALANCED; *node = grandchild; }}
(4)删掉树结构:包括删掉node的左子树,原树节点*data指向的AVL节点,AVL节点*data指向的数据,若node=NULL,则删除整个树
static void destroy_left(BisTree *tree, BiTreeNode *node){ BiTreeNode **position; if(tree->size == 0) return; //如果node等于NULL则从头节点开始删掉 if(node == NULL) position = &tree->root; else position = &node->left; if(*position != NULL) { //如果tree已经没有子叶,则destroy_left,destroy_right直接返回,继续执行下面的删除该节点 destroy_left(tree, *position); destroy_right(tree, *position); if(tree->destroy != NULL) { tree->destroy(((AvlNode *)bittree_data(position)->data)->data); } free((*position)->data); free(*position); *position = NULL; tree->size--; } return;}static void destroy_right(BisTree *tree, BiTreeNode *node){ BiTreeNode **position; if(tree->size == 0) return; //如果node等于NULL则从头节点开始删掉 if(node == NULL) position = &tree->root; else position = &node->right; if(*position != NULL) { destroy_left(tree, *position); destroy_right(tree, *position); if(tree->destroy != NULL) { tree->destroy(((AvlNode *)bittree_data(position)->data)->data); } free((*position)->data); free(*position); *position = NULL; tree->size--; } return;}
(5)向节点插入子节点,要考虑左插还是右插,是否需要旋转
//*node==NULL表示插入第一个节点static int insert(BisTree *tree, BiTreeNode **node, const void *data, int *balanced){ AvlNode *avl_data; int cmpval, retval;//cmpval是节点数据比较的结果,retval是返回的错误类型 if(*node == NULL) { if((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) return -1; avl_data->factor = AVL_BALANCED; avl_data->hidden = 0; avl_data->data = (void *)data; return bittree_ins_left(tree, *node, avl_data); } else { //比较数据大小决定往右边插还是往左边插 cmpval = tree->compare(data, ((AvlNode *)bittree_data(*node))->data); //判断大小,递归到最底层插入 if(cmpval < 0) { if(bittree_left(*node) == NULL) { if((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) return -1; avl_data->factor = AVL_BALANCED; avl_data->hidden = 0; avl_data->data = (void *)data; if(bittree_ins_left(tree, *node, avl_data) != 0) return -1; //在最底层插入后让*balance=0,才可进行旋转,只需要旋转最下面一颗不平衡的树 *balance = 0; } else { if((retval = insert(tree, &bittree_left(*node), data, balance)) != 0) return retval; } if(!(*balanced)) { //从插入节点的父节点开始,判断平衡,再到爷爷节点,只有这两层(除新插入的,最底的两层)需要判断 switch (((AvlNode *)bittree_data(*node))->factor) { case AVL_LFT_HEAVY: rotate_left(node); *balanced = 1; break; //本来平衡左插后左偏 case AVL_BALANCED: ((AvlNode *)bittree_data(*node))->factor = AVL_LFT_HEAVY; break; case AVL_REG_HEAVY: ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; *balanced = 1; break; } } } else if(cmpval > 0) { //到最底层才能插入 if(bittree_right(*node) == NULL) { if((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) return -1; avl_data->factor = AVL_BALANCED; avl_data->hidden = 0; avl_data->data = (void *)data; if(bittree_ins_right(tree, *node, avl_data) != 0) return -1; //*balance表示是否到达最底层,没到最底层的父树*balance都为1 *balance = 0; } else { if((retval = insert(tree, &bittree_right(*node), data, balance)) != 0) return retval; } if(!(*balanced)) { //现在是要往左边插入 switch (((AvlNode *)bittree_data(*node))->factor) { 本来就左偏,再左插就要旋转,递归旋转 case AVL_REG_HEAVY: rotate_right(node); *balanced = 1; break; //本来平衡右插后右偏 case AVL_BALANCED: ((AvlNode *)bittree_data(*node))->factor = AVL_REG_HEAVY; break; case AVL_LFT_HEAVY: ((AvlNode *)bittree_data(*node))->factor = AVL_BALANCED; *balanced = 1; break; } } } //cmpval==0,即和*node节点数据相等 else { //为了防止原数节点指向的数据和新加的相同,但是空间数据不同 if(!((AvlNode *)bittree_data(*node))->hidden) return 1; else { if(tree->destroy != NULL) { tree->destroy(((AvlNode *)bittree_data(*node))->data); } ((AvlNode *)bittree_data(*node))->data = (void *)data; ((AvlNode *)bittree_data(*node))->hidden = 0; *balanced = 1; } } } return 0;}
(6)标记节点是否已经在树中
//node是开始比较的节点static int hide(BisTree *tree, BiTreeNode *node, const void *data){ int cmpval, retval; //已经找到底 if(node == NULL) { return -1; } cmpval = tree->compare(data, ((AvlNode *)bittree_data(*node))->data); if(cmpval < 0) { retval = hide(tree, bittree_left(node), data); } else if(cmpval > 0) { retval = hide(tree, bittree_right(node), data); } else { ((AvlNode *)bittree_data(*node))->hidden = 1; retval = 0; } return retval;}
阅读全文
0 0
- 13、二叉搜索树-AVL树
- AVL平衡二叉搜索树
- AVL平衡搜索二叉树
- AVL平衡二叉搜索树
- 平衡二叉搜索树(AVL树)
- 算法二叉搜索树之AVL树
- AVL树(平衡二叉搜索树)
- AVL树(一种二叉平衡搜索树)
- 二叉搜索树之AVL树
- 二叉搜索树---AVL树删除节点
- 平衡二叉搜索树之AVL树
- 二叉搜索树-AVL树的实现
- 数据结构-平衡搜索二叉树(AVL树)
- AVL二叉搜索树的Rotation
- 二叉搜索树之—AVL
- 二叉树、二叉搜索树、AVL树的java实现
- [数据结构复习]树_二叉搜索树&AVL树
- 二叉树搜索树---AVL树插入节点
- 对Java中的深复制和浅复制的一些理解
- 迷宫大门
- c++ sort函数的用法
- golang http 编程-1(服务器编程)
- Access denied for user 'root'@'%' to database 'ranger' ErrorCode: 1044
- 13、二叉搜索树-AVL树
- 正则表达式匹配
- 数据结构-循环列表
- python3.6+mysql无法写入中文问题
- DBMS_SHARED_POOL包将对象固定到共享池 .
- Java死锁问题分析
- OJ text2 括号匹配问题
- 51nod-1085 背包问题【01背包】
- CDQZ Challenge 11