查找(AVL平衡二叉树)
【1】为什么需要平衡二叉树?
矛盾是推进事物向前发展的源动力。
那么平衡二叉树是从哪里来?肯定是有矛盾存在的。请看下面的分析:

【2】什么是平衡二叉树?
平衡二叉树的基本认识:

【3】平衡二叉树的构建原理
平衡二叉树的形成肯定是有一定规律可循的,那么平衡二叉树的“生长”原理是什么呢?
请看程老师下面的构建示例以及详细讲解:




关于平衡二叉树的旋转分为以下四种情况:

【4】平衡二叉树的实现
平衡二叉树的实现代码如下:
#include <iostream>
using namespace std; template<class Type>
class AVLtree; template<class Type>
class TNode
{
friend class AVLtree<Type>;
private:
Type data;
int balance; // 平衡因子
TNode<Type> *leftChild, *rightChild;
public:
TNode(const Type &x = Type(),TNode<Type> *left = NULL,TNode<Type> *right = NULL)
: data(x)
, leftChild(left)
, rightChild(right)
, balance()
{}
}; template<class Type>
class AVLtree
{
private:
TNode<Type> *root;
private:
void RightBalance(TNode<Type> * &r,bool &action);
void LeftBalance(TNode<Type> *&r,bool &action);
void Insert(TNode<Type> * &root,const Type &x,bool &action);
void LeftLeft(TNode<Type> * &r);
void RightRight(TNode<Type> * &r);
void LeftRight(TNode<Type> *&r);
void RightLeft(TNode<Type> *&r);
TNode<Type> *Parent(TNode<Type> *p,TNode<Type> *cur);
TNode<Type> *FindNodeNext(TNode<Type> *cur);
void DeleTNode(TNode<Type> *&cur,TNode<Type> *par);
void Remove(TNode<Type> * &r,const Type &x,bool &action);
void InOrder(TNode<Type> *p);
public:
AVLtree();
void Insert(const Type &bt);
TNode<Type> *Parent(TNode<Type> *cur);
void Remove(const Type &x);
void InOrder();
}; // 右平衡处理过程
template<class Type>
void AVLtree<Type>::RightBalance(TNode<Type> * &r, bool &action)
{
TNode<Type> *rightsub = r->rightChild, *leftsub = NULL;
switch (rightsub->balance) //判断右子树的平衡因子
{
case -: // RR型
r->balance = ;
rightsub->balance = ;
RightRight(r); //RR型处理
action = false;
break;
case :
break;
case : // RL型
leftsub = rightsub->leftChild;
switch (leftsub->balance) // 判断左子树的平衡因子
{
case : // RL型
r->balance = ;
rightsub->balance = ;
leftsub->balance = ;
break;
case : // RLL型
r->balance = ;
leftsub->balance = ;
rightsub->balance = -;
break;
case -: // RLR型
rightsub->balance = ;
leftsub->balance = ;
r->balance= -;
break;
}
RightLeft(r); // RL折线型转换处理
action = false;
break;
}
}
// 折线型LR处理
template<class Type>
void AVLtree<Type>::LeftRight(TNode<Type> *&r)
{
RightRight(r->leftChild); // 转换为LL型(一条直线)
LeftLeft(r); // LL型处理
}
// 折线型RL处理
template<class Type>
void AVLtree<Type>::RightLeft(TNode<Type> *&r)
{
LeftLeft(r->rightChild); // 先转换为RR型(一条直线)
RightRight(r); // RR型处理
}
// 1. 把RL转换为RR 2. LL型处理
template<class Type>
void AVLtree<Type>::LeftLeft(TNode<Type> * &r)
{
TNode<Type> *cur = r; // cur暂存r
r = r->leftChild; // 改变r就是改变根
cur->leftChild = r->rightChild;// 改变暂存cur 实现衔接
r->rightChild = cur; // 根的右子树置为cur
}
// 1. 把LR转换为LL 2. RR型处理
template<class Type>
void AVLtree<Type>::RightRight(TNode<Type> * &r)
{
TNode<Type> *cur = r; // cur暂存r
r = r->rightChild; // 改变r就是改变根
cur->rightChild = r->leftChild;// 改变暂存cur 实现衔接
r->leftChild = cur; // 根的左子树置为cur
}
// 左平衡处理过程
template<class Type>
void AVLtree<Type>::LeftBalance(TNode<Type> *&r, bool &action)
{
TNode<Type> *leftsub = r->leftChild;
TNode<Type> *rightsub = leftsub->rightChild;
switch (leftsub->balance)
{
case :// LL型
leftsub->balance = ;
r->balance = ;
LeftLeft(r);
action = false;
break;
case :
action = false;
break;
case -:// LR型
switch (rightsub->balance)
{
case :// LR型
r->balance = ;
rightsub->balance = ;
leftsub->balance = ;
break;
case -:// LRR型
r->balance = ;
rightsub->balance = ;
leftsub->balance = ;
break;
case :// LRL型
rightsub->balance = ;
leftsub->balance = ;
r->balance = -;
break;
}
LeftRight(r); // LR折线型转换处理
action = false;
break;
}
}
// Insert主函数
template<class Type>
void AVLtree<Type>::Insert(TNode<Type> * & root, const Type &x, bool &action)
{
if (NULL == root)
{
root = new TNode<Type>(x);
return;
}
else if (x > root->data)
{
Insert(root->rightChild, x, action);
if (action) // 右子树插入成功
{
switch (root->balance) // 需要重置根的平衡因子
{
case : // 表示左子树已经存在,现再插入右子树成功
root->balance = ; //平衡因子置0
break;
case : // 表示之前平衡,现再插入右子树成功
root->balance = -; //平衡因子置1
break;
case -: // 表示右子树已经存在,现再插入右子树成功
RightBalance(root, action); //右平衡
break;
}
}
}
else if (x < root->data)
{
Insert(root->leftChild, x, action);
if (action) // 左子树插入成功
{
switch (root->balance) // 需要重置根的平衡因子
{
case : // 平衡左子树
LeftBalance(root, action);
break;
case :
root->balance = ;
break;
case -:
root->balance = ;
action = false;
break;
}
}
}
else
cout << "数据" << x << "重复!" << endl;
}
// 查找当前节点的父节点
template<class Type>
TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *p, TNode<Type> *cur)
{
if (NULL == p || NULL == cur|| p == cur)
return NULL;
if (cur == p->leftChild || cur == p->rightChild)
return p; if (p->data < cur->data)
return Parent(p->rightChild, cur);
else
return Parent(p->leftChild, cur);
}
// 查找当前结点的后继 (先序遍历的后继)
template<class Type>
TNode<Type> *AVLtree<Type>::FindNodeNext(TNode<Type> *cur)
{
if (NULL == cur)
return NULL;
TNode<Type> *p = cur->rightChild;
while (p->leftChild != NULL)
{
p = p->leftChild;
}
return p;
}
//////////////////////////////////////////////////////////////////////
/////////////////////////////////删除节点
template<class Type>
void AVLtree<Type>::DeleTNode(TNode<Type> *&cur, TNode<Type> *par)
{
if (NULL == cur)
return;
// 情况一:删除的是根节点,那么它的父节点必定为NULL
if (NULL == par)
{ // cur可能是根结点,并且树仅仅只有一个根
if (NULL == cur->rightChild && NULL == cur->leftChild)
{
delete cur;
cur = NULL;
return;
}
// 单分支的树
if (NULL == cur->rightChild)
{ // 右子树不存在
TNode<Type> *p = cur;
cur = cur->leftChild;
delete p;
p = NULL;
return;
}
if (NULL == cur->leftChild)
{ // 左子树不存在
TNode<Type> *q = cur;
cur = cur->rightChild;
delete q;
q = NULL;
return;
}
}
// 情况二:删除的属于双分支的节点
if (cur->leftChild != NULL && cur->rightChild != NULL)
{
TNode<Type> *p = FindNodeNext(cur); // 锁定先序遍历的后继
// 情况一:
if (cur->rightChild == p)
{ // 说明右子树仅仅只有一个节点
cur->balance += ; // 删除之后平衡因子改变
cur->data = p->data; // 填充数据,意味着改变删除对象
cur->rightChild = p->rightChild; // 衔接数据
delete p; //删除节点p
p = NULL;
return;
}
// 情况二:
// 否则
TNode<Type> *q = Parent(p); // 找到父节点
if (q->balance != ) // 不等于0,说明删除后会影响根结点的平衡因子
cur->balance += ; // 调整根节点的平衡因子
// 否则
q->balance -= ; // 删除的是左节点,所以加一
cur->data = p->data; // 填充数据,意味着改变删除对象 q->leftChild = p->rightChild; // 衔接数据 // 最后才可以动手删除节点 删除节点 释放内存
delete p;
p = NULL;
return;
}
// 情况三:单分支(其中包括了叶子节点的情况)
if (NULL == cur->leftChild)
{
TNode<Type> *p = cur;
if (cur == par->leftChild)
par->leftChild = cur->rightChild; // 衔接数据
else
par->rightChild = cur->rightChild; // 衔接数据 delete p;
p = NULL;
return;
}
if (NULL == cur->rightChild)
{
TNode<Type> *q = cur;
if (cur == par->leftChild)
par->leftChild = cur->leftChild;
else
par->rightChild = cur->leftChild; delete q;
q = NULL;
return;
}
}
// 删除过程的主函数
template<class Type>
void AVLtree<Type>::Remove(TNode<Type> * &r, const Type &x, bool &action)
{
if (NULL == r)
return;
if (x == r->data)
{
TNode<Type> *cur = r; // 确定数据的节点信息
TNode<Type> *par = Parent(r);// 确定当前结点的父节点
DeleTNode(r, par); // 删除当前指针
return;
}
else if (x > r->data)
{ // 右边查找
Remove(r->rightChild, x, action);
if (action)
{
switch (r->balance)
{
case -: // 若原来为1,现在删除了右节点,应该为0
r->balance = ;
break;
//若原来为-1,现在又再右枝上删除了节点,
//树一定不平衡,需要左平衡调整
case :
LeftBalance(r, action);
action = false;
break;
case : // 若原来为0,现在删除了右节点,应该为-1
r->balance = ;
action = false;
break;
}
}
}
else if (x < r->data)
{
Remove(r->leftChild, x, action);
if (action)
{
switch (r->balance)
{
case -:// 若原来为1,现在又再左枝上删除了节点,
// 树一定不平衡,需要右平衡调整
RightBalance(r, action);
break;
case :// 若原来为-1,现在删除了左节点,应该为0
r->balance = ;
break;
case :// 若原来为0,现在删除了左节点,应该为1
r->balance = -;
action = false;
break;
}
}
}
} template<class Type>
AVLtree<Type>::AVLtree(): root(NULL)
{}
template<class Type>
void AVLtree<Type>::Insert(const Type &bt)
{
bool action = true;
Insert(root, bt, action);
}
template<class Type>
TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *cur)
{
return Parent(root, cur);
}
template<class Type>
void AVLtree<Type>::Remove(const Type &x)
{
bool action = true;
Remove(root, x, action);
}
template<class Type>
void AVLtree<Type>::InOrder(TNode<Type> *p)
{
if (p != NULL)
{
InOrder(p->leftChild);
cout << p->data << " ";
InOrder(p->rightChild);
}
}
template<class Type>
void AVLtree<Type>::InOrder()
{
InOrder(root);
cout << endl;
}
Good Good Study, Day Day Up.
顺序 选择 循环 总结
查找(AVL平衡二叉树)的更多相关文章
- 数据结构中很常见的各种树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)
数据结构中常见的树(BST二叉搜索树.AVL平衡二叉树.RBT红黑树.B-树.B+树.B*树) 二叉排序树.平衡树.红黑树 红黑树----第四篇:一步一图一代码,一定要让你真正彻底明白红黑树 --- ...
- 3.1 C语言_实现AVL平衡二叉树
[序] 上节我们实现了数据结构中最简单的Vector,那么来到第三章,我们需要实现一个Set set的特点是 内部有序且有唯一元素值:同时各种操作的期望操作时间复杂度在O(n·logn): 那么标准的 ...
- 数据结构【查找】—平衡二叉树AVL
/*自己看了半天也没看懂代码,下次再补充说明*/ 解释: 平衡二叉树(Self-Balancing Binary Search Tree 或Height-Balanced Binary Search ...
- 数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)
树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树 ...
- AVL平衡二叉树
AVL树 1.若它的左子树不为空,则左子树上所有的节点值都小于它的根节点值. 2.若它的右子树不为空,则右子树上所有的节点值均大于它的根节点值. 3.它的左右子树也分别可以充当为二叉查找树. 例如: ...
- 查找->动态查找表->平衡二叉树
文字描述 平衡二叉树(Balanced Binary Tree或Height-Balanced Tree) 因为是俄罗斯数学家G.M.Adel’son-Vel’skii和E.M.Landis在1962 ...
- InnoDB索引概述,二分查找法,平衡二叉树
索引是应用程序设计和开发的一个重要方面.如果索引太多,应用的性能可能会受到影响:如果索引太少,对查询性能又会产生影响.要找到一个合适的平衡点,这对应用的性能至关重要. 如果知道数据的使用,从一开始就应 ...
- PAT A1123 Is It a Complete AVL Tree (30 分)——AVL平衡二叉树,完全二叉树
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...
- AVL平衡二叉树实现,图解分析,C++描述,完整可执行代码
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
随机推荐
- Fiddler-004-配置过滤器之-域名过滤
前文讲述了通过 Fiddler 进行网络抓包的一个小实例,具体敬请参阅博文: 有些细心的小主可能发现了,我们捕获的 HTTP请求 中有一些请求不是我们需要的,而是一些非必要数据,页面如下图所示:
- C++经典编程题#1:含k个3的数
总时间限制: 1000ms 内存限制: 65536kB 描述 输入两个正整数 m 和 k,其中1 < m < 100000,1 < k < 5 ,判断 m 能否被19整除, ...
- 链表之求链表倒数第k个节点
题目描述:输入一个单向链表,输出该链表中倒数第k个节点,链表的倒数第0个节点为链表的尾指针. 最普遍的方法是,先统计单链表中结点的个数,然后再找到第(n-k)个结点.注意链表为空,k为0,k为1,k大 ...
- 深入理解BootStrap之栅格系统(布局)
1.栅格系统(布局) Bootstrap内置了一套响应式.移动设备优先的流式栅格系统,随着屏幕设备或视口(viewport)尺寸的增加,系统会自动分为最多12列. 我在这里是把Bootstrap中的栅 ...
- Ubuntu 安装软件
1,安装pthread的man文档 sudo apt-get install manpages-posix manpages-posix-dev
- 高性能Linux服务器 第6章 ext3文件系统反删除利器ext3grep extundelete工具恢复rm -rf 误删除的文件
高性能Linux服务器 第6章 ext3文件系统反删除利器ext3grep extundelete工具恢复rm -rf 误删除的文件 只能用于ext3文件系统!!!!!!!高俊峰(高性能Linux ...
- 视差效果原理 background-attachment:fixed
<html> <head> <style type="text/css"> body { background-image:url('http: ...
- Android各个版本 版本号对应关系表
Platform Version API Level VERSION_CODE Notes Android 5.0 21 LOLLIPOP Platform Highlights Android 4. ...
- php 读取webservice接口
开启 extension = php_soap.dll extension = php_curl.dll extension = php_openssl.dll <script src=&quo ...
- iOS 瀑布流的Demo
/** * 瀑布流Demo的主要代码,若想看完整的代码请到下面链接去下载 * * 链接: https://pan.baidu.com/s/1slByAHB 密码: r3q6 */ #import &l ...