数据结构——平衡二叉树(AVLTree)
3.平衡二叉树
平衡二叉树,又称AVL树,它是一种特殊的二叉排序树。
3.1 平衡二叉树的四种自旋
这个左旋、右旋,在方向上和我观念里的是相反的。
查了之后才知道:
1、外侧插入:LL、RR,都是在最边边上。
2、内侧插入:LR、RL,往里面来了些。
(1)LL旋转和RR旋转:
void RR_Rotate(AVLTree *root){ AVLTreeNode* rchild = (*root)->Right; (*root)->Right = rchild->Left; rchild->Left = *root; *root = rchild; } void LL_Rotate(AVLTree *root) { AVLTreeNode* lchild = (*root)->Left; (*root)->Left = lchild->Right; lchild->Right = *root; *root = lchild; }
(2)LR,RL型旋转(插入的节点在CL上 还是CR上是没有影响的)
LR型旋转图解
void LR_Rotate(AVLTree *root) { RR_Rotate(&(*root)->Left); return LL_Rotate(root); } void RL_Rotate(AVLTree *root) { LL_Rotate(&(*root)->Right); RR_Rotate(root); }
小结:几个子树在水平位置上顺序是不会变的!根节点和根节点的子树在水平上的逻辑位置也是不会变的。
3.2 平衡二叉树的插入
插入算法就是出现不平衡状态时,判断需要使用哪种旋转方式来使得二叉树保持平衡:
AVLTree InsertAVLTree(AVLTree root, int x) { if (root == NULL) { root = new AVLTreeNode; root->Left = NULL; root->Right = NULL; root->data = x; return root; } if (x > root->data) { root->Right = InsertAVLTree(root->Right, x); //递归返回插入位置的父节点或者祖父……,如果失去了平衡 ) { //如果插入的值大于,当前节点的左孩子节点,说明该节点是插在root的右子树上的 if (x > root->Left->data) RR_Rotate(&root); else RL_Rotate(&root); } } else if (x < root->data) { root->Left = InsertAVLTree(root->Left, x); ) { if (x < root->Left->data) LL_Rotate(&root); else LR_Rotate(&root); } } else { cout << "the number is already included." << endl; return NULL; } return root; }
3.3 平衡二叉树的删除
之前写过二叉排序树的节点的删除的话,这里会好写很多,就是多出来一个判断从哪个子树删除节点的问题。
void AVLTreeDel(AVLTree *root, int data) { if (!*root) { cout << "delete failed" << endl; return; } AVLTreeNode *p = *root; if (data == p->data) { //左右子树都非空 if (p->Left && p->Right) { //在高度更大的那个子树上进行删除操作 //进左子树,右转到底,进右子树,左转到底,转弯碰壁,杀孩子。 if (height(p->Left) > height(p->Right)) { AVLTreeNode *pre=NULL,*q = p->Left; if (!q->Right) q->Right = p->Right; else { while (q->Right) { pre = q; q = q->Right; } pre->Right = q->Left; q->Left = p->Left; q->Right = p->Right; } *root = q; } else { AVLTreeNode *pre = NULL, *q = p->Right; if (!q->Left) q->Left = p->Left; else { while (q->Left) { pre = q; q = q->Left; } pre->Left = q->Right; q->Left = p->Left; q->Right = p->Right; } *root=q; } } else (*root) = (*root)->Left ? (*root)->Left : (*root)->Right; delete p; } else if (data < p->data){//要删除的节点在左子树中 //在左子树中进行递归删除 AVLTreeDel(&(*root)->Left, data); //判断是否仍然满足平衡条件 ){ //如果当前节点右孩子的左子树更高 if (height(p->Right->Left) > height(p->Right->Right)) RL_Rotate(root); else RR_Rotate(root); } } else{ AVLTreeDel(&(*root)->Right, data); ) { if (height((*root)->Left->Left) > height((*root)->Left->Right)) LL_Rotate(root); else LR_Rotate(root); } } }
https://www.2cto.com/kf/201702/556250.html
完整代码(2019.1.20):
#pragma once #include "top.h" typedef BTreeNode AVLTreeNode, *AVLTree; void RR_Rotate(AVLTree *root){ AVLTreeNode* Right = (*root)->Right; (*root)->Right = Right->Left; Right->Left = *root; *root = Right; } void LL_Rotate(AVLTree *root) { AVLTreeNode* Left = (*root)->Left; (*root)->Left = Left->Right; Left->Right = *root; *root = Left; } void LR_Rotate(AVLTree *root) { RR_Rotate(&(*root)->Left); return LL_Rotate(root); } void RL_Rotate(AVLTree *root) { LL_Rotate(&(*root)->Right); RR_Rotate(root); } AVLTree AVLTreeInsert(AVLTree root, int x) { if (root == NULL) { root = new AVLTreeNode; root->Left = NULL; root->Right = NULL; root->data = x; return root; } if (x > root->data) { root->Right = AVLTreeInsert(root->Right, x); //递归返回插入位置的父节点或者祖父……,如果失去了平衡 ) { //如果插入的值大于,当前节点的右孩子节点,说明该节点是插在root的右子树上的 //if (x > root->Left->data) RR_Rotate(&root);不能保证该节点一定有左子树 if (x > root->Right->data)RR_Rotate(&root); else RL_Rotate(&root); } } else if (x < root->data) { root->Left = AVLTreeInsert(root->Left, x); ) { if (x < root->Left->data) LL_Rotate(&root); else LR_Rotate(&root); } } else { cout << "the number is already included." << endl; return NULL; } return root; } AVLTree AVLTreeCreat(int *a, int length) { AVLTree T = NULL; ; i < length; i++) { T = AVLTreeInsert(T, a[i]); } return T; } AVLTreeNode* AVLFind(AVLTree T, int x) { AVLTreeNode *p = T; while (p) { if (x == p->data) break; p = x > p->data ? p->Right : p->Left; } return p; } AVLTree AVLMax(AVLTree p) { if (!p) return NULL; if (p->Right == NULL) return p; return AVLMax(p->Right); } AVLTree AVLMin(AVLTree p) { if (!p) return NULL; if (p->Left == NULL) return p; return AVLMin(p->Left); } void AVLTreeDel(AVLTree *root, int data) { if (!*root) { cout << "delete failed" << endl; return; } AVLTreeNode *p = *root; if (data == p->data) { //左右子树都非空 if (p->Left && p->Right) { //在高度更大的那个子树上进行删除操作 //进左子树,右转到底,进右子树,左转到底,转弯碰壁,杀孩子。 if (height(p->Left) > height(p->Right)) { AVLTreeNode *pre=NULL,*q = p->Left; if (!q->Right) q->Right = p->Right; else { while (q->Right) { pre = q; q = q->Right; } pre->Right = q->Left; q->Left = p->Left; q->Right = p->Right; } *root = q; } else { AVLTreeNode *pre = NULL, *q = p->Right; if (!q->Left) q->Left = p->Left; else { while (q->Left) { pre = q; q = q->Left; } pre->Left = q->Right; q->Left = p->Left; q->Right = p->Right; } *root=q; } } else (*root) = (*root)->Left ? (*root)->Left : (*root)->Right; delete p; } else if (data < p->data){//要删除的节点在左子树中 //在左子树中进行递归删除 AVLTreeDel(&(*root)->Left, data); //判断是否仍然满足平衡条件 ){ //如果当前节点右孩子的左子树更高 if (height(p->Right->Left) > height(p->Right->Right)) RL_Rotate(root); else RR_Rotate(root); } } else{ AVLTreeDel(&(*root)->Right, data); ) { if (height((*root)->Left->Left) > height((*root)->Left->Right)) LL_Rotate(root); else LR_Rotate(root); } } } void checkCreat() { ; ); ; i < length; i++) { cout << a[i] << ","; } cout << endl; AVLTree T = AVLTreeCreat(a, length); int t = rand() % length; AVLTreeDel(&T, a[t]); ; i++) { a[i] = a[i + ]; } Preorder(T); cout << endl; Inorder(T); cout << endl; Postorder(T); cout << endl; free(a); }
数据结构——平衡二叉树(AVLTree)的更多相关文章
- 什么是泛型?,Set集合,TreeSet集合自然排序和比较器排序,数据结构-二叉树,数据结构-平衡二叉树
==知识点== 1.泛型 2.Set集合 3.TreeSet 4.数据结构-二叉树 5.数据结构-平衡二叉树 ==用到的单词== 1.element[ˈelɪmənt] 要素 元素(软) 2.key[ ...
- 数据结构-平衡二叉树 旋转过程平衡因子分析 c和java代码实现对比
平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且 ...
- java——平衡二叉树 AVLTree、AVLMap、AVLSet
平衡二叉树:对于任意一个节点,左子树和右子树的高度差不能超过1 package Date_pacage; import java.util.ArrayList; public class AVLTre ...
- 平衡二叉树(AVLTREE,双链表实现)
首先说下好久没更新了,最近打游戏和工作都有点多,o(^▽^)o. 写这个AVL发现自己的代码风格好差,尤其是变量命名这块,后来意识到了,想去改,但是太多了,改了几个就不想改了,做这个是记录下自己的成长 ...
- Java数据结构——平衡二叉树的平衡因子(转自牛客网)
若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性.首先要找出插入新结点后失去平衡的最小子树根结点的指针.然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树.当失去平衡的最小子树被 ...
- 大话数据结构—平衡二叉树(AVL树)
平衡二叉树(Self-Balancing Binary Search Tree/Height-Balanced Binary Search Tree),是一种二叉排序树,当中每个节点的左子树和右子树的 ...
- 数据结构-平衡二叉树Java实现
1,Node.java package com.cnblogs.mufasa.BalanceBinaryTree; public class Node { Node parent; Node left ...
- JavaScript数据结构——树的实现
在计算机科学中,树是一种十分重要的数据结构.树被描述为一种分层数据抽象模型,常用来描述数据间的层级关系和组织结构.树也是一种非顺序的数据结构.下图展示了树的定义: 在介绍如何用JavaScript实现 ...
- 20162325 金立清 S2 W8 C17
20162325 2017-2018-2 <程序设计与数据结构>第8周学习总结 教材学习内容概要 二叉查找树是一棵二叉树,对于其中的每个结点,左子树上的元素小于父结点的值,而右子树上的元素 ...
随机推荐
- ssm项目快速搭建(注解)-依赖
父层jar包版本控制,管理配置 <!-- 集中定义依赖版本号 --> <properties> <junit.version>4.12</ ...
- ZOJ 1049 判断坐标点
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=49 水题 #include<iostream> #include&l ...
- Java 的 委托 是什么?
前言:在学习设计模式时,发现书中有多次提到委托二字,所以经过网上搜索得到结果,并自己写了个小小的例子. 什么是委托? 委托模式是软件设计模式中的一项基本技巧.在委托模式中,有两个对象参与处理同一个请求 ...
- Myeclipse中设置jsp页面的默认编码格式
在MyEclispe中创建Jsp页面,Jsp页面的默认编码是“ISO-8859-1”,如下图所示: 在这种编码下编写中文是没有办法保存Jsp页面的,会出现如下的错误提示: 因此可以设置Jsp默认的编码 ...
- 为什么推荐用ui-router替代ngRoute
初学angularjs,第一个实例是官网的phoneCat,里面路由用的是ngRoute,后来看到别的用ui-router,觉得好奇,ui-route是什么呢?百度一些,得到如下解释: ui-rout ...
- SignalR实时通信
/// <summary> /// Message集线器类 /// </summary> [HubName("chathub")] public class ...
- 汇编语言程序环境搭建masm+debug64位 win10/7
介绍:MASM是Microsoft Macro Assembler 的缩写,是微软公司为x86 微处理器家族开发的汇编开发环境,拥有可视化的开发界面,使开发人员不必再使用DOS环境进行汇编的开发,编译 ...
- IOS CALayer的属性和使用
一.CALayer的常用属性 1.@propertyCGPoint position; 图层中心点的位置,类似与UIView的center:用来设置CALayer在父层中的位置:以父层的左上角为原点( ...
- linux day4
echo $? :上一次命令是否执行正确make clean :清理编译垃圾文件env :查询环境变量 安装pip下载软件源cat /etc/pip.conf [global] index-url = ...
- jQuery的安装
一.jQuery的安装 下载 jQuery 有两个版本的 jQuery 可供下载: Production version - 用于实际的网站中,已被精简和压缩. Development version ...