数据结构--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;
else
return P->Hight;
} static int Element(Position P) //返回节点的元素
{
if(P == NULL)
return -1000;
else
return P->Element;
} int Max(int i,int j) //返回最大值
{
if(i > j)
return i;
else
return 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);
else
T = 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);
else
T = 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);
else
father = 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);
else
father = 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);
else
T = 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);
else
T = 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; }
递归与栈的使用有着不可描述的关系,就像雪穗和亮司一样,我觉得如果要把递归函数改写成非递归的函数,首先要想到用栈。
唉,夜似乎更深了。
数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作的更多相关文章
- 二叉查找树(BST)、平衡二叉树(AVL树)(只有插入说明)
二叉查找树(BST).平衡二叉树(AVL树)(只有插入说明) 二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点, ...
- Java数据结构——AVL树
AVL树(平衡二叉树)定义 AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,并且拥有自平衡机制.在AV ...
- 二叉树中序遍历,先序遍历,后序遍历(递归栈,非递归栈,Morris Traversal)
例题 中序遍历94. Binary Tree Inorder Traversal 先序遍历144. Binary Tree Preorder Traversal 后序遍历145. Binary Tre ...
- 左神算法基础班4_1&2实现二叉树的先序、中序、后序遍历,包括递归方式和非递归
Problem: 实现二叉树的先序.中序.后序遍历,包括递归方式和非递归方式 Solution: 切记递归规则: 先遍历根节点,然后是左孩子,右孩子, 根据不同的打印位置来确定中序.前序.后续遍历. ...
- JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)
JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...
- [复习] JAVA 遍历目录 (递归调用和非递归)
JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...
- 再回首数据结构—AVL树(一)
前面所讲的二叉搜索树有个比较严重致命的问题就是极端情况下当数据以排序好的顺序创建搜索树此时二叉搜索树将退化为链表结构因此性能也大幅度下降,因此为了解决此问题我们下面要介绍的与二叉搜索树非常类似的结构就 ...
- JAVA数据结构--AVL树的实现
AVL树的定义 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度都是.增 ...
- AVL树的创建--C语言实现
AVL树是一种自平衡(Self-balancing)二叉查找树(Binary Search Tree),要求任何一个节点的左子树和右子树的高度之差不能超过1. AVL树的插入操作首先会按照普通二叉查找 ...
随机推荐
- EasyUI 学习笔记
EasyUI常见错误 1 . 无论是用HMTL形式实现组件还是使用代码 + HTML 形式实现组件 , 在为组件设置属性时 , 要注意属性值的类型问题 string:必须加引号 number:不加任何 ...
- VisualVM使用方法
VisualVM 简介 VisualVM 是一个工具,它提供了一个可视界面,用于查看 Java 虚拟机 (Java Virtual Machine, JVM) 上运行的基于 Java 技术的应用程序( ...
- JSON字符串书写
{ "XXX公司": [ { "name": "IT部", "mebers": [ { "维护人员&quo ...
- BZOJ 1597 土地购买(斜率优化DP)
如果有一块土地的长和宽都小于另一块土地的长和宽,显然这块土地属于“赠送土地”. 我们可以排序一下将这些赠送土地全部忽略掉,一定不会影响到答案. 那么剩下的土地就是长递减,宽递增的.令dp[i]表示购买 ...
- 【hdu4507】吉哥系列故事——恨7不成妻 数位dp
题目描述 求 $[L,R]$ 内满足:数位中不包含7.数位之和不是7的倍数.本身不是7的倍数 的所有数的平方和 mod $10^9+7$ . 输入 输入数据的第一行是case数T(1 <= T ...
- Git更新github项目
1. 把github上你想要更新修改的项目克隆到本地 $ git clone https://github.com/delav/test.git 2. 根据自己需求对项目进行修改 3. 把项目放到缓存 ...
- 【题解】51nod 1686第K大区间
成功的秘诀,在于克服自己看题解的冲动……[笑哭].自己A掉这题还是灰常开心的~ 以及爱死 two - pointer ! two - pointer 大法是真的好哇……这个题目有上一题的经验:求第\( ...
- 用Matlab对数据进行线性拟合算法
http://www.cnblogs.com/softlin/p/5965939.html 挖坑
- BZOJ1596 [Usaco2008 Jan]电话网络 【树形dp】
题目链接 BZOJ1596 题解 先抽成有根树 设\(f[i][0|1][0|1]\)表示以\(i\)为根,儿子都覆盖了,父亲是否覆盖,父亲是否建塔的最少建塔数 转移一下即可 #include< ...
- ContestHunter暑假欢乐赛 SRM 04
逃了一场SRM(躺 A题可以看成0点到1点,有p的几率从0到1,1-p几率不动,求0到1的期望步数.很显然概率是不降序列数/n!,然后列个方程E[0] = E[0] * (1 - p) + 1,解得E ...