【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平衡二叉树)的更多相关文章

  1. 数据结构中很常见的各种树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

    数据结构中常见的树(BST二叉搜索树.AVL平衡二叉树.RBT红黑树.B-树.B+树.B*树) 二叉排序树.平衡树.红黑树 红黑树----第四篇:一步一图一代码,一定要让你真正彻底明白红黑树 --- ...

  2. 3.1 C语言_实现AVL平衡二叉树

    [序] 上节我们实现了数据结构中最简单的Vector,那么来到第三章,我们需要实现一个Set set的特点是 内部有序且有唯一元素值:同时各种操作的期望操作时间复杂度在O(n·logn): 那么标准的 ...

  3. 数据结构【查找】—平衡二叉树AVL

    /*自己看了半天也没看懂代码,下次再补充说明*/ 解释: 平衡二叉树(Self-Balancing Binary Search Tree 或Height-Balanced Binary Search ...

  4. 数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

    树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树 ...

  5. AVL平衡二叉树

    AVL树 1.若它的左子树不为空,则左子树上所有的节点值都小于它的根节点值. 2.若它的右子树不为空,则右子树上所有的节点值均大于它的根节点值. 3.它的左右子树也分别可以充当为二叉查找树. 例如: ...

  6. 查找->动态查找表->平衡二叉树

    文字描述 平衡二叉树(Balanced Binary Tree或Height-Balanced Tree) 因为是俄罗斯数学家G.M.Adel’son-Vel’skii和E.M.Landis在1962 ...

  7. InnoDB索引概述,二分查找法,平衡二叉树

    索引是应用程序设计和开发的一个重要方面.如果索引太多,应用的性能可能会受到影响:如果索引太少,对查询性能又会产生影响.要找到一个合适的平衡点,这对应用的性能至关重要. 如果知道数据的使用,从一开始就应 ...

  8. 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 ...

  9. AVL平衡二叉树实现,图解分析,C++描述,完整可执行代码

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

随机推荐

  1. PySe-001-基础环境配置(MacOX)

    Python 是一种面向对象.解释型计算机程序设计语言,其源代码同样遵循 GPL(GNU General Public License)协议.Python语法简洁而清晰,具有丰富和强大的类库.由于Py ...

  2. Sql server与Excel的数据互通导入导出

    现在,我先从Sql server数据表导出到Excel中,再从Excel数据表导出到Sql server中: 一.Sql server数据表导出到Excel中: 1.新建一个Excel,选择“数据”菜 ...

  3. imx6 uboot lvds clock

    在uboot中添加logo,lvds接口的lcd显示不正常,出现波动.网上说是lvds时钟频率的问题. 使用示波器测量之后,发现频率是60M,而lcd最大频率才46.8M. 因此就需要更改uboot中 ...

  4. http://www.cnblogs.com/peida/archive/2013/04/23/3036035.html

    http://www.cnblogs.com/peida/archive/2013/04/23/3036035.html

  5. 前端开发者需要的10个Sublime插件

    Sublime Text是最强大的代码编辑器之一,它具有一些神奇的功能,而且可以通过安装插件或包来变得更强大.这些插件为Sublime Text添加了额外的功能.当今有很多插件可以用来满足几乎任何你的 ...

  6. [PCL]NDT点云匹配方法

    测试NDT方法的Demo,http://pointclouds.org/documentation/tutorials/normal_distributions_transform.php#norma ...

  7. APN 推送

    推送的各种状态 http://samwize.com/2015/08/07/how-to-handle-remote-notification-with-background-mode-enabled ...

  8. 由浅到深讲解C#-LINQ

    在说LINQ之前必须先说说几个重要的C#语言特性 一:与LINQ有关的语言特性 1.隐式类型 (1)源起 在隐式类型出现之前, 我们在声明一个变量的时候, 总是要为一个变量指定他的类型 甚至在fore ...

  9. css 正方体

    <!DOCTYPE html><html lang="zh-cmn-Hans"><head><meta charset="utf ...

  10. linux: centos设置ip以及连接外网

    注明:我使用的的使centos 7,所有文件名是ifcfg-enp0s3, 一. 设置虚拟机中linux的ip,使本地能连通虚拟机的linux系统 1>.进入本地windows的cmd,输入ip ...