数据结构--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树的插入操作首先会按照普通二叉查找 ...
随机推荐
- 第22天:js改变样式效果
一.输出语句 1.alert:弹出警示框(用的非常少,用户体验不好)完整写法:window.alert(“执行语句”):window对象,窗口,一般情况可省略alert(123); 2.console ...
- Python 开篇及第一个Python程序
本节内容 python 简单介绍 python 2.x 或者python 3.x python 安装 第一个python程序 一.python简单介绍 python的创始人为吉多.范罗苏姆(Guido ...
- P1483 序列变换
题目描述 给定一个由n个整数构成的序列,你需要对它进行如下操作: 操作1:输入格式“1 x y”,表示把所有a[kx](k为正整数,kx<=n)都加上y. 操作2:输入格式“2 j”,表示输出a ...
- BZOJ5334:[TJOI2018]数学计算——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5334 小豆现在有一个数x,初始值为1. 小豆有Q次操作,操作有两种类型: 1 m: x = x ...
- BZOJ2301:[HAOI2011]Problem b——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2301 https://www.luogu.org/problemnew/show/P2522 对于给 ...
- git安装和使用 linux系统和window系统
一.git简介 git是一款免费.开放源代码的分布式版本控制系统特点: git是一个开源的分布式版本控制系统,可以有效, 高速的处理从很小到非常大的项目版本管理 二.git安装 Linux:下载.安装 ...
- PHP 数据库防止攻击
定义和用法 mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符. 下列字符受影响: \x00 \n \r \ ' " \x1a 如果成功, ...
- thrift源码阅读笔记
http://note.youdao.com/noteshare?id=3f3cf77bf70656ac626f7bf2099063c7
- oepncv-学习笔记一
安装opencv文件时若需要cmake编译,如果中间出现 解决办法是: 在opencv的文件中找到包含cmakelist.txt的文件夹,把where is the source code:的路径改成 ...
- [解决] Error Code: 1044. Access denied for user 'root'@'%' to database
今天在测试集群用的mysql上,遇到个权限的问题: SQLException : SQL state: 42000 com.mysql.jdbc.exceptions.jdbc4.MySQLSynta ...