二叉查找树是个好东西,他让查找,插入,删除,这些常用操作变得高效,但是,他是存在问题的,那就是,在坏的输入序列下,树会退化成链表,这就很尴尬了,于是为了避免这种情况的发生,我们需要一种数据结构,可以自动对树进行调整,我们希望树尽量平衡,于是我们使用平衡因子作为指标,保持任意节点左右子树深度差不超过1,这就可以让树的深度很理想了(接近log2N),如何对树进行调整呢?我们通过旋转来完成他。

#include <iostream>
#include <queue> class AVLT{//小于向左,大于等于向右,元素类型需支持 <
private:
typedef int Element;
struct AVLTNode{
Element data;
AVLTNode *left;
AVLTNode *right;
int Deepth;
AVLTNode();
~AVLTNode();
bool isLeaf()const;
void nodeInsect(const Element &e);
void nodeDelete(const Element &e);
const AVLTNode *Find(const Element &e)const;
const Element& Min()const;
const Element& Max()const;
void nodeTraverseFrist(std::ostream& os = std::cout)const;
void nodeTraverseMid(std::ostream& os = std::cout)const;
void nodeTraverseLast(std::ostream& os = std::cout)const;
void nodeTraverselevel(std::ostream& os = std::cout)const;
const AVLTNode & operator =(const AVLTNode &T);
void swapdata(AVLTNode&a, AVLTNode&b)const;
void SingleLeftRotation();
void SingleRightRotation();
void DoubleRightLeftRotation();
void DoubleLeftRightRotation();
inline void renewDeepth();
inline int max(int a, int b)const;
};
AVLTNode *node;
int number_of_Node;
public:
AVLT();
AVLT(Element *arr, int size);
AVLT(const AVLT &T);
~AVLT();
bool empty()const;
const Element& Max()const;
const Element& Min()const;
const AVLT &operator = (const AVLT&T);
void TraverseFrist(std::ostream& os = std::cout)const;
void TraverseLast(std::ostream& os = std::cout)const;
void TraverseMid(std::ostream& os = std::cout)const;
void Traverselevel(std::ostream& os = std::cout)const;
void Insect(const AVLT::Element &e);
bool Delete(const AVLT::Element &e);
int Deepth();
int Node();
const AVLTNode* find(const Element &e)const;
}; AVLT::AVLTNode::AVLTNode():left(NULL), right(NULL), Deepth(){}
AVLT::AVLTNode::~AVLTNode(){
delete left;
delete right;
}
bool AVLT::AVLTNode::isLeaf()const{
return left == NULL&&right == NULL;
}
void AVLT::AVLTNode::nodeInsect(const Element &e){
if (Deepth == ){
Deepth = ;
data = e;
return;
}
if (e<data){
if (left == NULL){
left = new AVLTNode;
}
left->nodeInsect(e);
if (right){
if (left->Deepth - right->Deepth > ){
if (e<left->data){
this->SingleRightRotation();
}
else{
this->DoubleLeftRightRotation();
}
}
}
else{
if (left->Deepth > ){
if (e<left->data){
this->SingleRightRotation();
}
else{
this->DoubleLeftRightRotation();
}
}
}
renewDeepth();
}
else{
if (right == NULL){
right = new AVLTNode;
}
right->nodeInsect(e);
if (left){
if (right->Deepth - left->Deepth > ){
if (e<right->data){
this->DoubleRightLeftRotation();
}
else{
this->SingleLeftRotation();
}
}
}
else{
if (right->Deepth > ){
if (e<right->data){
this->DoubleRightLeftRotation();
}
else{
this->SingleLeftRotation();
}
}
}
renewDeepth();
}
return;
}
void AVLT::AVLTNode::nodeDelete(const Element &e){
if (e<data){
if (left){
if (left->isLeaf()){
delete left;
left = NULL;
}
else
left->nodeDelete(e);
{
int rd = right ? right->Deepth : ;
int ld = left ? left->Deepth : ;
if (rd - ld >){
if (right->left){
DoubleRightLeftRotation();
}
else{
SingleLeftRotation();
}
}
renewDeepth();
}
}
return;
}
else{
if (data<e){
if (right){
if (right->isLeaf()){
delete right;
right = NULL;
}
else
right->nodeDelete(e);
{
int rd = right ? right->Deepth : ;
int ld = left ? left->Deepth : ;
if (ld - rd >){
if (left->right){
DoubleLeftRightRotation();
}
else{
SingleRightRotation();
}
}
renewDeepth();
}
return;
}
}
else{
if (left == NULL&&right){
AVLTNode *t = right;
if (left)
delete left;
left = t->left;
right = t->right;
data = t->data;
Deepth -= ;
t->left = t->right = NULL;
delete t;
return;
}
else{
if (right == NULL && left){
AVLTNode *t = left;
if (right)
delete right;
right = t->right;
left = t->left;
data = t->data;
Deepth -= ;
t->left = t->right = NULL;
delete t;
return;
}
else{ AVLTNode *t = left;
while (t->right)
t = t->right;
Element te = t->data;
if (left->isLeaf()){
delete left;
left = NULL;
}
else
left->nodeDelete(te);
data = te;
return;
}
}
}
}
std::cout << "return false" << std::endl;
return;
}
AVLT::AVLTNode const *AVLT::AVLTNode::Find(const Element &e)const{
if (e<data){
if (left)
return left->Find(e);
}
else{
if (data<e){
if (right)
return right->Find(e);
}
else{
return this;
}
}
return NULL;
}
const AVLT::Element& AVLT::AVLTNode::Max()const{
const AVLTNode *t = this;
while (t->right)
t = t->right;
return t->data;
}
const AVLT::Element& AVLT::AVLTNode::Min()const{
const AVLTNode *t = this;
while (t->left)
t = t->left;
return t->data;
}
void AVLT::AVLTNode::nodeTraverseFrist(std::ostream& os)const{
os << this->data << ' ';
if (left)
this->left->nodeTraverseFrist();
if (right)
this->right->nodeTraverseFrist();
}
void AVLT::AVLTNode::nodeTraverseMid(std::ostream& os )const{
if (left)
this->left->nodeTraverseMid();
os << this->data << ' ';
if (right)
this->right->nodeTraverseMid();
}
void AVLT::AVLTNode::nodeTraverseLast(std::ostream& os )const{
if (left)
this->left->nodeTraverseLast();
if (right)
this->right->nodeTraverseLast();
os << this->data << ' ';
}
void AVLT::AVLTNode::nodeTraverselevel(std::ostream& os)const{
std::queue<AVLTNode> q;
q.push(*this);
while (!q.empty()){
AVLTNode p = q.front();
q.pop();
os << p.data << ' ';
if (p.left){
q.push(*(p.left));
}
if (p.right){
q.push(*(p.right));
}
}
}
const AVLT::AVLTNode & AVLT::AVLTNode::operator =(const AVLTNode &T){
if (Deepth == ){
Deepth = ;
data = T.data;
}
if (T.left){
if (left == NULL){
left = new AVLTNode;
}
*left = *T.left;
if (right){
Deepth = max(left->Deepth, right->Deepth) + ;
}
else{
Deepth = left->Deepth + ;
}
}
if (T.right){
if (right == NULL){
right = new AVLTNode;
}
*right = *T.right;
if (left){
Deepth = max(left->Deepth, right->Deepth) + ;
}
else{
Deepth = right->Deepth + ;
}
}
return *this;
}
void AVLT::AVLTNode::swapdata(AVLTNode&a, AVLTNode&b)const{
Element t;
t = a.data;
a.data = b.data;
b.data = t;
}
void AVLT::AVLTNode::SingleLeftRotation(){
AVLTNode *a = right;
right = a->right;
a->right = a->left;
a->left = left;
left = a;
if (a->right&&a->left){
a->Deepth = max(a->left->Deepth, a->right->Deepth) + ;
}
else
if (a->left){
a->Deepth = a->left->Deepth + ;
}
else{
a->Deepth = ;
}
swapdata(*this, *a);
}
void AVLT::AVLTNode::SingleRightRotation(){
AVLTNode *a = left;
left = a->left;
a->left = a->right;
a->right = right;
right = a;
if (a->right&&a->left){
a->Deepth = max(a->left->Deepth, a->right->Deepth) + ;
}
else
if (a->left){
a->Deepth = a->left->Deepth + ;
}
else{
a->Deepth = ;
}
swapdata(*this, *a);
}
void AVLT::AVLTNode::DoubleLeftRightRotation(){
this->left->SingleLeftRotation();
this->SingleRightRotation();
}
void AVLT::AVLTNode::DoubleRightLeftRotation(){
this->right->SingleRightRotation();
this->SingleLeftRotation();
}
inline void AVLT::AVLTNode::renewDeepth(){
Deepth = max(left ? left->Deepth : , right ? right->Deepth : ) + ;
}
inline int AVLT::AVLTNode::max(int a, int b)const{
return a > b ? a : b;
} AVLT::AVLT():node(NULL), number_of_Node(){
}
AVLT::AVLT(Element *arr, int size) : node(NULL), number_of_Node(){
node = new AVLTNode;
for (int i = ; i < size; i++)
this->Insect(arr[i]);
}
AVLT::AVLT(const AVLT &T) : node(NULL), number_of_Node(){
*this = T;
}
AVLT::~AVLT(){
delete node;
}
bool AVLT::empty()const{
return node == NULL;
}
const AVLT::Element& AVLT::Max()const{
return node->Max();
}
const AVLT::Element& AVLT::Min()const {
return node->Min();
}
const AVLT &AVLT::operator = (const AVLT&T){
delete node;
node = new AVLTNode;
number_of_Node = T.number_of_Node;
*node = *T.node;
return *this;
}
void AVLT::TraverseFrist(std::ostream& os )const{
if (node)
node->nodeTraverseFrist(os);
}
void AVLT::TraverseLast(std::ostream& os )const{
if (node)
node->nodeTraverseLast(os);
}
void AVLT::TraverseMid(std::ostream& os )const{
if (node)
node->nodeTraverseMid(os);
}
void AVLT::Traverselevel(std::ostream& os )const{
if (node)
node->nodeTraverselevel(os);
}
void AVLT::Insect(const AVLT::Element &e){
number_of_Node++;
if (node == NULL){
node = new AVLTNode;
}
node->nodeInsect(e);
}
bool AVLT::Delete(const AVLT::Element &e){
if (node){
if (node->isLeaf()){
delete node;
node = NULL;
}
else
node->nodeDelete(e);
number_of_Node--;
return true;
}
else{
return false;
}
}
int AVLT::Deepth(){
return node->Deepth;
}
int AVLT::Node(){
return number_of_Node;
}
const AVLT::AVLTNode*AVLT::find(const AVLT::Element &e)const {
if (node)
return node->Find(e);
else
return NULL;;
}
std::ostream& operator << (std::ostream& os, const AVLT& T){
T.TraverseFrist(os);
return os;
}
const AVLT& find();

这样看上去,AVL树似乎完胜普通的二叉查找树,但是现实是,坏的序列往往很少出现,很多时候,普通二叉树因为不需要判断平衡因子,旋转这些操作,效率反而更高,但是他一旦对上坏的序列就无计可施了,想能防住坏的序列,但又不想每次都旋转,于是就有伸展树这种数据结构,他只在坏的序列出现时旋转,但是只有“坏到一定

程度才旋转”,于是会出现比较坏但坏得不彻底的尴尬情况,伸展树无法保证每次操作都是O(log2N),但是能保证M次操作时间复杂度为O(Mlog2N)。

C++类实现AVL树的更多相关文章

  1. AVL树(C++&Java)

    目录 AVL Tree精讲专题 前言 一.AVL Tree for CPP(Coding) 1.AVL树原型 2.旋转的四种方式 二.完整版AVL Tree的CPP和JAVA实现 AVL Tree C ...

  2. 数据结构与算法——AVL树类的C++实现

    关于AVL树的简单介绍能够參考:数据结构与算法--AVL树简单介绍 关于二叉搜索树(也称为二叉查找树)能够參考:数据结构与算法--二叉查找树类的C++实现 AVL-tree是一个"加上了额外 ...

  3. 算法与数据结构(十一) 平衡二叉树(AVL树)

    今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...

  4. AVL树

    AVL树 在二叉查找树(BST)中,频繁的插入操作可能会让树的性能发生退化,因此,需要加入一些平衡操作,使树的高度达到理想的O(logn),这就是AVL树出现的背景.注意,AVL树的起名来源于两个发明 ...

  5. 数据结构图文解析之:AVL树详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  6. 一步一步写平衡二叉树(AVL树)

    平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵 ...

  7. AVL树模板

    ///AVL树模板 typedef struct Node ///树的节点 { int val,data; int h; ///以当前结点为根结点的数的高度 int bf; ///平衡因子(左子树高度 ...

  8. poj 3841 Double Queue (AVL树入门)

    /****************************************************************** 题目: Double Queue(poj 3481) 链接: h ...

  9. AVL树(三)之 Java的实现

    概要 前面分别介绍了AVL树"C语言版本"和"C++版本",本章介绍AVL树的Java实现版本,它的算法与C语言和C++版本一样.内容包括:1. AVL树的介绍 ...

随机推荐

  1. Linux Shell脚本之自动修改IP

    作为一名Linux SA,日常运维中很多地方都会用到脚本,而服务器的ip一般采用静态ip或者MAC绑定,当然后者比较操作起来相对繁琐,而前者我们可以设置主机名.ip信息.网关等配置.修改成特定的主机名 ...

  2. Python3 函数式编程

    函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用.而允许使用变量的程序设计语言,由 ...

  3. yum使用详细

    1.使用YUM查找软件包 命令:yum search~ 2.列出所有可安装的软件包 命令:yum list 3.列出所有可更新的软件包 命令:yum list updates 4.列出所有已安装的软件 ...

  4. 数据库MySQL与xls文件的互导

    最近的一个项目需要将xls表导入到MySQL数据库中和将MySQL数据表导出到xls表中,在网上搜了很多资料,经过多次尝试终于实现了功能,废话不多说,在这粘贴出代码,希望可以帮到需要的朋友. 一.将. ...

  5. NDK_ROOT找不到的解决方法 MACOS

    只要在Eclipse上进行配置就行了,看图说话  

  6. SORT_AREA_RETAINED_SIZE

    manual pga: SORT_AREA_RETAINED_SIZE specifies (in bytes) the maximum amount of the user global area ...

  7. POJ 1129 Channel Allocation 四色定理dfs

    题目: http://poj.org/problem?id=1129 开始没读懂题,看discuss的做法,都是循环枚举的,很麻烦.然后我就决定dfs,调试了半天终于0ms A了. #include ...

  8. 单片微机原理P0:80C51结构原理

    本来我真的不想让51的东西出现在我的博客上的,因为51这种东西真的太low了,学了最多就所谓的垃圾科创利用一下,但是想一下这门课我也要考试,还是写一点东西顺便放博客上吧. 这一系列主要参考<单片 ...

  9. ORACLE 常用系统函数

    1.  字符类 1.1  ASCII(c ) 函数  和CHR( i )      ASCII 返回一个字符的ASCii码,其中c表示一个字符;CHR 返回ascii码值i 所对应的字符 . 如: S ...

  10. Mysql大表查询优化技巧总结及案例分析

    http://www.169it.com/article/3219955334.html     sql语句使用基本原则:1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 orde ...