数据结构--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树的插入操作首先会按照普通二叉查找 ...
随机推荐
- vc6.0批量加注释
MATLAB批量加注释的方法非常简单明了,加注释是ctrl+R,去注释是ctrl+T 然后在VC中我对一条一条加注释的方法非常烦恼,我想也许会有简单的方法可以批量家注释.果然,先贴代码 '------ ...
- Qt入门实例
一.基于Qt设计师 1.创建一个GUI项目,选择“Qt4 Gui Application”.其中还有Empty Qt4 Project(空的工程),Qt4 Console Applicaiton(基于 ...
- POJ 2785 4 Values whose Sum is 0(折半枚举)
给出四个长度为n的数列a,b,c,d,求从这四个数列中每个选取一个元素后的和为0的方法数.n<=4000,abs(val)<=2^28. 考虑直接暴力,复杂度O(n^4).显然超时. # ...
- CodeForces 632E Thief in a Shop
题意:给你n种物品,每种无限个,问恰好取k个物品能组成哪些重量.n<=1000,k<=1000,每种物品的重量<=1000. 我们搞出选取一种物品时的生成函数,那么只要对这个生成函数 ...
- Java的第一个程序-Hello, World !
学了一个月的Java,现在总结一下,就算复习了. 一.安装Java环境 这个没啥好说的. 1. 官网下载JDK安装 2. 配置环境变量.注意的是:环境变量配置好以后,如果cmd中运行 java 命令没 ...
- AtCoder Regular Contest 075 E - Meaningful Mean(树状数组)
题目大意:求一个数组中,平均值不小于k的连续子序列个数 所有数减去k,算个前缀和出来,就变成二维数点问题了. 没有修改,离线的话就是CZL所说的“NOIP最喜欢的套路”了:倒着加进BIT,以权值为数组 ...
- X day3
题目 官方题解 T1: 一道水题 #include<iostream> #include<cstring> #include<cstdio> #include< ...
- 【状压DP】【UVA11795】 Mega Man's Mission
传送门 Description 你要杀n个怪,每杀掉一个怪那个怪会掉落一种武器,这种武器可以杀死特定的怪.游戏初始你有一把武器,能杀死一些怪物.每次只能杀一只,求有多少种杀怪方法. Input 多组数 ...
- [ZJOI2010]排列计数 (组合计数/dp)
[ZJOI2010]排列计数 题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有 ...
- Connections between cities LCA
Problem Description After World War X, a lot of cities have been seriously damaged, and we need to r ...