数据结构--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树的插入操作首先会按照普通二叉查找 ...
随机推荐
- 使用Gulp实现网页自动刷新:gulp-connect
入门指南 1. 全局安装 gulp: npm install --global gulp 2. 作为项目的开发依赖(devDependencies)安装: npm install --save-dev ...
- c#对xml的操作
操作xml可以通过XElement对象,比较方便的使用列举以下几点: 把字符串转变成XElement,保存成xml文件,加载xml文件: //把字符串解析成XElement对象 string str ...
- java基础简介
一.软件开发 软件:是由数据和指令组成的(例:计算器) 如何实现软件开发呢? 就是使用开发工具和计算机语言做出东西来 二.常用dos命令 d: 回车 盘符切换 dir(directory):列出 ...
- 实用图像处理入门 - 1 - opencv VS2012 环境搭建
标签中的部分 font-family: 华文细黑; font-size: 26px; font-weight: bold; color: #611427; margin-top:40px; } h2 ...
- bzoj1086-王室联邦
题目 给出一棵树,求一种分块方案,使得每个块的大小\(size\in [B,3B]\).每个块还要选一个省会,省会可以在块外,但是省会到块内任何一个点路径上的所有除了省会的点都必须属于这个块.\(n\ ...
- 【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组
题目描述 Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型.每一张卡片都由一些数字进行标记,第i张卡片的序列 ...
- C# 代码操作XML(增、删、改)
目录: 1.创建XML 1)创建普通XML 2)创建带属性的XML 2.追加XML 3.读取XML 1)读取普通XML 2)读取带属性的XML 4.修改属性的值 5.删除XML节点 作为一个小型的数 ...
- 一些技巧 && 常数优化 && 出现の错误
开坑原因 7.21 今天DTZ大爷教了我一个算欧拉函数的好方法......是质因数复杂度的 这让我想到,这些小技巧小idea,很多时候,可能就是考场上最致命.最一击必杀的"大招" ...
- BZOJ2821:作诗——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2821 问题描述 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好 ...
- LOJ2350:[JOI2017/2018决赛]月票购买——题解
https://loj.ac/problem/2350 比较简单的题,为什么我实现得这么sb? 第一个包其实已经给了提示(第一个包的解法就是在S->T所有最短路径上的所有点到V的最短路的最小值. ...