AVL树本质上还是一棵二叉搜索树,它的特点是:

1.本身首先是一棵二叉搜索树。
2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1)。
也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树)。
对Avl树进行相关的操作最重要的是要保持Avl树的平衡条件。即对Avl树进行相关的操作后,要进行相应的旋转操作来恢复Avl树的平衡条件。
对Avl树的插入和删除都可以用递归实现,文中也给出了插入的非递归版本,关键在于要用到栈。
代码如下:
#include <iostream>
#include<stack>
using namespace std;struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *Avltree;struct AvlNode    //AVL树节点
{int Element;Avltree Left;Avltree Right;int Hight;int Isdelete;  //指示该元素是否被删除
};///AVL平衡树的函数的相关声明//
Avltree MakeEmpty(Avltree T);   //清空一棵树
static int Height(Position P);  //返回节点的高度
Avltree Insert(int x, Avltree T);   //在树T中插入元素x
Avltree Insert_not_recursion (int x, Avltree T);  //在树T中插入元素x,非递归版本
Position FindMax(Avltree T);   //查找Avl树的最大值,和二叉树一样
Avltree Delete(int x,Avltree T);   //删除元素,非懒惰删除///AVL平衡树的函数的相关定义//
Avltree MakeEmpty(Avltree T)
{if (T != NULL){MakeEmpty(T->Left);MakeEmpty(T->Right);delete T;// free(T);}return NULL;
}static int Height(Position P)   //返回节点的高度
{if(P == NULL)return -1;elsereturn P->Hight;
}static int Element(Position P)   //返回节点的元素
{if(P == NULL)return -1000;elsereturn P->Element;
}int Max(int i,int j)    //返回最大值
{if(i > j)return i;elsereturn j;
}static Position SingleRotateWithLeft (Position k2)   //单旋转,左子树高度比较高
{Position k1;k1 = k2->Left;k2->Left = k1->Right;k1->Right = k2;k2->Hight = Max(Height(k2->Left), Height(k2->Right)) + 1;k1->Hight = Max(Height(k1->Left), Height(k1->Right)) + 1;return k1;  //新的根
}static Position SingleRotateWithRight (Position k1)   //单旋转,右子树的高度比较高
{Position k2;k2 = k1->Right;k1->Right = k2->Left;k2->Left = k1;k1->Hight = Max(Height(k1->Left), Height(k1->Right)) + 1;k2->Hight = Max(Height(k2->Left), Height(k2->Right)) + 1;return k2;  //新的根
}static Position DoubleRotateWithLeft (Position k3)   //双旋转,当k3有左儿子而且k3的左儿子有右儿子
{k3->Left = SingleRotateWithRight(k3->Left);return SingleRotateWithLeft(k3);
}static Position DoubleRotateWithRight (Position k1)   //双旋转,当k1有右儿子而且k1的又儿子有左儿子
{k1->Right = SingleRotateWithLeft(k1->Right);return SingleRotateWithRight(k1);
}//对Avl树执行插入操作,递归版本
Avltree Insert(int x, Avltree T)
{if(T == NULL)  //如果T为空树,就创建一棵树,并返回{T = static_cast<Avltree>(malloc(sizeof(struct AvlNode)));if (T == NULL){cout << "out of space!!!" << endl;}else                    {T->Element = x;T->Left = NULL;T->Right = NULL;T->Hight = 0;T->Isdelete = 0;}}else   //如果不是空树{if(x < T->Element){T->Left = Insert(x,T->Left);if(Height(T->Left) - Height(T->Right) == 2 ){if(x < T->Left ->Element )T = SingleRotateWithLeft(T);elseT = DoubleRotateWithLeft(T);}}else{if(x > T->Element ){T->Right = Insert(x,T->Right );if(Height(T->Right) - Height(T->Left) == 2 ){if(x > T->Right->Element )T = SingleRotateWithRight(T);elseT = DoubleRotateWithRight(T);}}}}T->Hight = Max(Height(T->Left), Height(T->Right)) + 1;return T;
}//对Avl树进行插入操作,非递归版本
Avltree Insert_not_recursion (int x, Avltree T)
{stack<Avltree> route; //定义一个堆栈使用//找到元素x应该大概插入的位置,但是还没进行插入Avltree root = T;while(1){if(T == NULL)  //如果T为空树,就创建一棵树,并返回{T = static_cast<Avltree>(malloc(sizeof(struct AvlNode)));if (T == NULL) cout << "out of space!!!" << endl;  else                    {T->Element = x;T->Left = NULL;T->Right = NULL;T->Hight = 0;T->Isdelete = 0;route.push (T);break;}}else if (x < T->Element){route.push (T);T = T->Left;continue;}else if (x > T->Element){route.push (T);T = T->Right;continue;}else{T->Isdelete = 0;return root;}}//接下来进行插入和旋转操作Avltree father,son;while(1){son = route.top ();   route.pop();   //弹出一个元素if(route.empty())return son;   father = route.top ();  route.pop();   //弹出一个元素if(father->Element < son->Element )   //儿子在右边{father->Right = son;if( Height(father->Right) - Height(father->Left) == 2){if(x >  Element(father->Right))father = SingleRotateWithRight(father);elsefather = DoubleRotateWithRight(father);}route.push(father);}else if (father->Element > son->Element)    //儿子在左边{father->Left = son;if(Height(father->Left) - Height(father->Right) == 2){if(x < Element(father->Left))father = SingleRotateWithLeft(father);elsefather = DoubleRotateWithLeft(father);}route.push(father);}father->Hight = max(Height(father->Left),Height(father->Right )) + 1;}}Position FindMax(Avltree T)
{if(T != NULL){while(T->Right != NULL){T = T->Right;}}return T;
}Position FindMin(Avltree T)
{if(T == NULL){return NULL;}else{if(T->Left == NULL){return T;}else{return FindMin(T->Left );}}
}Avltree Delete(int x,Avltree T)    //删除Avl树中的元素x
{Position Temp;if(T == NULL)return NULL;else if (x < T->Element)   //左子树平衡条件被破坏{T->Left = Delete(x,T->Left );if(Height(T->Right) - Height(T->Left) == 2){if(x > Element(T->Right) )T = SingleRotateWithRight(T);elseT = DoubleRotateWithRight(T);  }}else if (x > T->Element)   //右子树平衡条件被破坏{T->Right = Delete(x,T->Right );if(Height(T->Left) - Height(T->Right) == 2){if(x < Element(T->Left) )T = SingleRotateWithLeft(T);elseT = DoubleRotateWithLeft(T);  }}else    //执行删除操作{if(T->Left && T->Right)   //有两个儿子{Temp = FindMin(T->Right);T->Element = Temp->Element;T->Right = Delete(T->Element ,T->Right);}else  //只有一个儿子或者没有儿子{Temp = T;if(T->Left == NULL)T = T->Right;else if(T->Right == NULL)T = T->Left;free(Temp);}}return T;
}int main ()
{Avltree T = NULL;T = Insert_not_recursion(3, T);  //T一直指向树根T = Insert_not_recursion(2, T);T = Insert_not_recursion(1, T);T = Insert_not_recursion(4, T);T = Insert_not_recursion(5, T);T = Delete(1,T);// T = Insert_not_recursion(6, T);/*  T = Insert(3, T);  //T一直指向树根T = Insert(2, T);T = Insert(1, T);T = Insert(4, T);T = Insert(5, T);T = Insert(6, T);*/cout << T->Right->Right->Element << endl;return 0;}

    递归与栈的使用有着不可描述的关系,就像雪穗和亮司一样,我觉得如果要把递归函数改写成非递归的函数,首先要想到用栈。

唉,夜似乎更深了。

转载于:https://www.cnblogs.com/1242118789lr/p/6803906.html

数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作相关推荐

  1. 二叉树创建,递归遍历,非递归遍历

    二叉树 博主是一个大一刚刚放暑假的大学生,大学我们只学习了c语言,现在这么卷只学c语言肯定不够,所以博主打算从零开始恶补c++顺便写文章记录一下,另外博主这个暑假还想记录一些算法基础内容欢迎关注哦.这 ...

  2. 二叉树中序遍历(递归法和迭代法(非递归法))——C++

    声明:本文原题主要来自力扣,记录此博客主要是为自己学习总结,不做任何商业等活动! 二叉树的遍历有前序遍历.中序遍历.后序遍历和层次遍历,其中二叉树基本知识点可以参考博主上篇博客(二叉树基本知识点图文介 ...

  3. 算法练习day10——190328(二叉树的先序、 中序、 后序遍历, 包括递归方式和非递归方式、找到一个节点的后继节点、二叉树的序列化和反序列化)

    1.实现二叉树的先序. 中序. 后序遍历, 包括递归方式和非递归方式 1.1 访问节点的顺序 节点访问顺序如下图所示: 访问顺序:1 2 4 4 4 2 5 5 5 2 1 3 6 6 6 3 7 7 ...

  4. 二叉树先中后序递归遍历与非递归遍历、层次遍历

    文章目录 1 先序遍历 1.1 先序遍历递归 1.2 先序遍历非递归 2 中序遍历 2.1 中序遍历递归 2.2 中序遍历非递归 3 后序遍历 3.1 后序遍历递归 3.2 后序遍历非递归 4 层序遍 ...

  5. C++-二叉树递归遍历与非递归遍历实现

    -二叉树递归遍历与非递归遍历实现 引言 0 有关线性表结点定义-LinkNode 1 栈的链式存储结构实现-LinkedStack 2 队列的链式存储结构实现-LinkedQueue 3 二叉树的链式 ...

  6. 二叉树的递归遍历和非递归遍历实现(C++)(深度优先)

    二叉树的递归遍历和非递归遍历(C++) 二叉树的遍历方式可分为先序遍历,中序遍历和后序遍历 先序遍历:先遍历根节点,再遍历左子节点,最后遍历右子节点. 中序遍历:先遍历左子节点,再遍历根节点,最后遍历 ...

  7. 规范化的递归转换成非递归

    递归函数被调用时,系统需要一个运行栈.系统的运行栈要保存函数的返回地址,保存调用函数的局部变量,每一层递归调用所需保存的信息构成运行栈的一个工作记录,在没进入下一层递归调用是,系统就会建立一个新的工作 ...

  8. java 文件 递归_JAVA实现遍历文件夹下的所有文件(递归调用和非递归调用)

    JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...

  9. 递归函数就兔子数C语言,【C语言】求斐波那契(Fibonacci)数列通项(递归法、非递归法)...

    意大利的数学家列昂那多·斐波那契在1202年研究兔子产崽问题时发现了此数列.设一对大兔子每月生一对小兔子,每对新生兔在出生一个月后又下崽,假若兔子都不死亡.问:一对兔子,一年能繁殖成多少对兔子?题中本 ...

最新文章

  1. linux vi编辑 整理
  2. 计算机科学和Python编程导论(三) 一些简单的数值程序
  3. L2-002. 链表去重
  4. 每天学一点flash (20) flash cs3.0 外部加载图片
  5. Hive表与hdfs文件关联
  6. mysql timestamp类型字段 自动更新为当前时间
  7. 转移指令的原理---汇编学习笔记
  8. 新闻系统查询思路和步骤
  9. matlab simulink笔记05 —— 积分模块
  10. mysql if语句后面执行两个语句_MySQL的if,case语句使用总结
  11. python黑洞_史上第一张黑洞照片是用Python合成的?
  12. 基于linux的服务有哪些内容,linux基础(一)服务分类与管理
  13. 罗永浩与银联合作直播,但因过程太流畅被网友调侃是录播
  14. The jQuery HTML5 Audio / Video Library
  15. python百分号转义_python 转义字符、运算符、列表。。。。
  16. Linux下MySQL数据库的备份与还原
  17. 网吧计费管理系统(武汉理工大学大一下实验(C语言版源码))
  18. 三角波电流与梯形波电流的分析
  19. 轻量级架构和重量级架构
  20. 如何增加架设传奇服务器

热门文章

  1. 【Python绘图】绘制Mascot
  2. 嵌入式系统一般由嵌入式微处理器、外围硬件设备、嵌入式操作系统
  3. 分享下我常用的客户开发方法及思路
  4. 离线下载工具(扒页面)
  5. iOS 隐藏电量信息、信号等状态信息状态栏
  6. 服务器本地系统 网络受限,windows10网络受限怎么解决_win10本地系统网络受限解决方法...
  7. 计算机类和鼠标类是什么关系,UML考试试题及答案7.doc
  8. 富人是怎么赚钱的?富人赚钱的底层逻辑是什么?
  9. Delphi 环境下使用DirectDraw实现简单的绘制
  10. Flutter学习笔记(18)--Drawer抽屉组件