AVL树插入删除

合集下载

C++实现AVL树的完整代码

C++实现AVL树的完整代码

C++实现AVL树的完整代码AVL树的介绍AVL树是⼀种⾃平衡的⼆叉搜索树,它通过单旋转(single rotate)和双旋转(double rotate)的⽅式实现了根节点的左⼦树与右⼦树的⾼度差不超过1,。

这有效的降低了⼆叉搜索树的时间复杂度,为O(log n)。

那么,下⾯⼩编将详细介绍C++实现AVL 树的代码。

最后⼀步提供可靠的代码实现这⾥先粘贴代码给⼤家的忠告,⼀定要及时去实现,不然之后再实现要花更多的时间/**平衡⼆叉树应该有些功能*插⼊删除查找*前序遍历中序遍历后序遍历层次遍历*统计结点数⽬*///代码已经调好,写了很久才写出来#ifndef _AVLTREE_#define _AVLTREE_#include<iostream>#include<vector>#include<queue>#include<map>using namespace std;#define MAXFACTOR = 2;template<class Key , class E>class AVLNode{private:Key key;E value;AVLNode<Key,E>* left;AVLNode<Key,E>* right;AVLNode<Key,E>* parent;public:AVLNode():left(nullptr),right(nullptr),parent(nullptr){}AVLNode(Key _key,E _value , AVLNode<Key,E>* _parent = nullptr,AVLNode<Key,E>*_left = nullptr, AVLNode<Key,E>*_right = nullptr):key(_key),value(_value),left(_left),right(_right),parent(_parent){}bool isLeaf(){return left==nullptr && right == nullptr ;}//元素设置Key getKey() const { return key;}void setKey(Key set) {key = set;}E getValue() const { return value;}void setValue(E set) {value = set;}AVLNode<Key,E>* getLeft() { return left; }void setLeft (AVLNode< Key,E >* set){ left = set;}AVLNode<Key,E>* getRight() { return right;}void setRight (AVLNode<Key,E>* set) {right = set ;}AVLNode<Key,E>* getParent() {return parent;}void setParent(AVLNode<Key,E>* set) { parent = set;}};template<class Key , class E>class AVLTree{private:AVLNode<Key,E>* root;void clear(AVLNode<Key,E>* &r){if(r==nullptr)return;delete r;}void Init(){root = new AVLNode<Key,E>();root=nullptr;}void preOrder(AVLNode<Key,E>* r,void(*visit) (AVLNode<Key,E> * node)) {if(r==nullptr)return;(*visit) (r);preOrder(r->getLeft() , visit);preOrder(r->getRight(), visit);}void inOrder(AVLNode<Key,E>* r , void(*visit)(AVLNode<Key,E>* node) ) {if(r==nullptr)return;inOrder(r->getLeft() , visit);(*visit)(r);inOrder(r->getRight(),visit);}void postOrder(AVLNode<Key,E>*r , void (*visit) (AVLNode<Key,E>* node)) {if(r==nullptr)return;postOrder(r->getLeft(),visit);postOrder(r->getRight(),visit);(*visit)(r);}void levelOrder(AVLNode<Key,E>*r , void (*visit) (AVLNode<Key,E>* node)) {queue< AVLNode<Key,E>* > q;if(r==nullptr)return;q.push(r);while( ! q.empty() ){AVLNode<Key,E>* tmp = q.front();q.pop();(*visit)(tmp);if(tmp->getLeft() ) q.push(tmp->getLeft() );if(tmp->getRight()) q.push(tmp->getRight());}}AVLNode<Key,E>* find(AVLNode<Key,E>* r,Key k){if(r==nullptr)return nullptr;if(k == r->getKey() ) return r;else if( k < r->getKey()){find(r->getLeft(),k);}else {find(r->getRight(),k);}}//Find the smallest element in the avl treeAVLNode<Key,E>* getMin(AVLNode<Key,E>* r){if(r->getLeft() == nullptr) return r;else{getMin(r->getLeft());}}//Remove the smallest elementAVLNode<Key,E>* deleteMin(AVLNode<Key,E>* rt){if(rt->getLeft() == nullptr) return rt->getRight();else{rt->setLeft(deleteMin(rt->getLeft()));}AVLNode<Key,E>* leftRotate(AVLNode<Key,E>* node){if( node == nullptr) return nullptr;AVLNode<Key,E>* newHead = node->getRight();node->setRight( newHead -> getLeft() );newHead -> setLeft( node );return newHead;}AVLNode<Key,E>* rightRotate(AVLNode<Key,E>* node){if(node == nullptr)return nullptr;AVLNode<Key,E>* newHead = node->getLeft();node->setLeft( newHead->getRight() );newHead ->setRight(node);return newHead;}int getHeight(AVLNode<Key,E>*node){if(node == nullptr)return 0;if(node->isLeaf())return 1;else return ( getHeight( node->getLeft() ) > getHeight( node->getRight() ) ? getHeight( node->getLeft() ) : getHeight( node->getRight() ) ) + 1; }int getBalanceFactor(AVLNode<Key,E>* node){return getHeight(node->getLeft()) - getHeight(node->getRight() );}AVLNode<Key,E>* balance(AVLNode<Key,E>* node){if(!node) return nullptr;else if ( getBalanceFactor( node ) == 2){if(getBalanceFactor( node ->getLeft() ) == 1){node = rightRotate(node);}else{node->setLeft(leftRotate( node->getLeft() ) );node = rightRotate(node);}}else if(getBalanceFactor( node ) == -2){if(getBalanceFactor( node->getRight()) == -1){node = leftRotate(node);}else{node->setRight( rightRotate( node->getRight() ) );node = leftRotate(node);}}return node;}AVLNode<Key,E>* insert( AVLNode<Key,E>* root ,const pair<Key,E>& it) {if(root == nullptr){return new AVLNode<Key,E>(it.first , it.second,NULL,NULL,NULL);}else if (it.first < root->getKey() ){root ->setLeft( insert(root->getLeft() , it) ) ;}else{root ->setRight( insert(root->getRight() , it) );root = balance(root);return root;}AVLNode<Key,E>* remove(AVLNode<Key,E>* node , const Key k){if(node == nullptr) return nullptr;if(node->getKey() > k){node->setLeft( remove(node->getLeft() , k) );node = balance(node);}else if(node->getKey() < k){node->setRight( remove(node->getRight(), k) );node = balance(node);}else if(node->getKey() == k){if(! node->isLeaf() ){AVLNode<Key,E>* tmp = getMin(node->getRight() );node->setKey( tmp->getKey() );node->setValue( tmp->getValue() );node->setRight( deleteMin(node->getRight() ) );delete tmp;}else {AVLNode<Key,E>* tmp = node;node = (node->getLeft() != nullptr) ? node->getLeft() : node->getRight() ; delete tmp;}}return node;}public:~AVLTree(){clear(root);}AVLTree(){/*Init();*/ root = nullptr; }//四种遍历⽅式void preOrder( void (*visit)(AVLNode<Key,E>* r)){preOrder(root,visit);}void inOrder(void (*visit)(AVLNode<Key,E>* r)){inOrder(root,visit);}void postOrder(void (*visit)(AVLNode<Key,E>* r)){postOrder(root,visit);}void levelOrder( void(*visit)(AVLNode<Key,E>*r) ){levelOrder(root,visit);}//插⼊void insert(const pair<Key,E> &it){root = insert(root,it);}//删除void remove(const Key& k){remove(root,k);}bool find(const Key&k){return find(root,k);}};#endif//AVLtest.cpp#include"NewAvl.h"#include<iostream>using namespace std;template<typename Key,typename E>void traverse(AVLNode<Key,E>* root){cout<<root->getKey()<<" "<<root->getValue()<<" "; cout<<endl;}int main(){AVLTree<int,int>* tree = new AVLTree<int ,int>; for(int i = 0 ; i < 5 ; i ++){tree->insert(make_pair(i,i));}tree->remove(1);cout<<"PreOrder: "<<endl;tree->preOrder(traverse);cout<<endl;cout<<"LevelOrder: "<<endl;tree->levelOrder(traverse);cout<<endl;cout<<"InOrder: "<<endl;tree->inOrder(traverse);cout<<endl;cout<<"PostOrder: "<<endl;tree->postOrder(traverse);cout<<endl;cout<<tree->find(2)<<endl;tree->insert(make_pair(9,9));tree->levelOrder(traverse);}运⾏结果以上就是C++实现AVL树的完整代码的详细内容,更多关于C++ AVL树的资料请关注其它相关⽂章!。

avl使用规则

avl使用规则

AVL树是一种自平衡二叉搜索树,其使用规则如下:
当插入一个新节点时,需要进行旋转操作以保持树的平衡。

旋转操作包括单旋转和双旋转,具体使用哪种旋转取决于插入节点后树的平衡情况。

在删除一个节点时,也需要进行旋转操作来重新平衡树。

同样地,旋转操作包括单旋转和双旋转,具体使用哪种旋转取决于删除节点后树的平衡情况。

除了插入和删除操作外,其他基本操作如搜索、查找等与普通的二叉搜索树类似。

需要注意的是,AVL树虽然能保证查询效率较高,但在插入和删除节点时需要进行旋转操作,这些操作可能会使得时间复杂度不再是O(log n),因此在数据量很大且插入删除频率较高的情况下,可能会比普通的二叉搜索树性能较差。

以上是关于AVL树使用规则的简要介绍,如有需要,可以阅读数据结构相关书籍或请教专业人士。

树结构的定义和基本操作

树结构的定义和基本操作

树结构的定义和基本操作树结构是一种非线性的数据结构,其形状类似于自然界中的树。

树由一组节点(或称为顶点)和一组连接这些节点的边组成。

树结构的常见学习对象有二叉树、二叉树、AVL树、红黑树等。

树结构的基本操作包括创建、插入、删除、查找和遍历。

首先,创建树结构需要定义树节点的结构。

每个节点至少包含一个数据元素以及指向其子节点的指针。

树结构可以使用链式存储结构或数组存储结构。

1.创建树结构:树结构的创建有多种方式。

其中一种常见的方法是通过递归实现。

递归函数首先创建根节点,然后再递归地创建根节点的左子树和右子树。

2.插入节点:要插入一个新节点,首先要定位到合适的位置。

比较要插入的节点值与当前节点值的大小,如果小于当前节点,则进入左子树,如果大于当前节点,则进入右子树。

最终找到合适的位置插入新节点。

如果要插入的节点已经存在,可以替换或忽略该节点。

3.删除节点:删除节点分为三种情况:删除叶子节点、删除只有一个子节点的节点、删除有两个子节点的节点。

-删除叶子节点:直接删除即可。

-删除只有一个子节点的节点:将子节点与父节点连接起来,删除当前节点。

-删除有两个子节点的节点:找到当前节点的后继节点(比当前节点大的最小节点),将后继节点的值复制到当前节点,然后删除后继节点。

4.查找节点:树的查找可以使用递归或迭代的方式实现。

递归方式从根节点开始,根据节点值与目标值的大小关系递归地遍历左子树或右子树,直到找到目标值或遍历完成。

迭代方式使用循环和栈或队列的数据结构来实现。

5.遍历节点:树的遍历有三种方式:前序遍历、中序遍历和后序遍历。

-前序遍历:根节点->左子树->右子树-中序遍历:左子树->根节点->右子树-后序遍历:左子树->右子树->根节点树的遍历也可以通过递归或迭代的方式实现。

递归方式较为简单,使用迭代方式需要借助栈或队列来保存遍历的节点。

除了上述基本操作外,树结构还有一些扩展的操作,如树的深度计算、查找最大值或最小值、查找前驱节点或后继节点等。

AVL树的c语言实现

AVL树的c语言实现

AVL树的c语言实现AVL树的c语言实现导语:C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的'机器码以及不需要任何运行环境支持便能运行的编程语言。

下面我们来看看AVL树的c语言实现,希望对大家有所帮助。

AVL树的c语言实现:在计算机科学中,AVL树是最先发明的自平衡二叉查找树。

在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。

查找、插入和删除在平均和最坏情况下都是O(log n)。

增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

1.节点(1)节点的定义1 2 3 4 5 6 7 8 9 typedef int KeyType;typedef struct AvlNode{KeyType key; //数据AvlNode *leftchild; //左孩子AvlNode *rightchild; //右孩子AvlNode *parent; //双亲结点int balance; //平衡因子}AvlNode,*AvlTree;(2)结点的创建1 2 3 4 5 6 7 8 9101112 AvlNode *BuyNode(){AvlNode *p =(AvlNode *)malloc(sizeof(AvlNode));if( p != NULL){p->leftchild = NULL;p->rightchild = NULL;p->parent = NULL;p->balance = 0;}return p;}2.旋转如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。

这种失去平衡的可以概括为4种姿态:左单旋转,右单旋转,左平衡,右平衡。

(1)左单旋转:也叫左左旋转。

【AVL树的c语言实现】。

算法工程师面试真题单选题100道及答案解析

算法工程师面试真题单选题100道及答案解析

算法工程师面试真题单选题100道及答案解析1. 以下哪种数据结构适合用于实现快速查找最大值和最小值?A. 栈B. 队列C. 堆D. 链表答案:C解析:堆可以快速地获取最大值和最小值。

2. 快速排序在最坏情况下的时间复杂度是?A. O(nlogn)B. O(n^2)C. O(n)D. O(logn)答案:B解析:快速排序在最坏情况下,每次划分都极不均匀,时间复杂度为O(n^2)。

3. 以下哪种算法常用于在未排序的数组中查找特定元素?A. 冒泡排序B. 二分查找C. 顺序查找D. 插入排序答案:C解析:顺序查找适用于未排序的数组查找特定元素。

4. 一个有向图的邻接表存储结构中,顶点的邻接点是按照什么顺序存储的?A. 随机顺序B. 顶点编号的大小顺序C. 插入的先后顺序D. 无法确定答案:C解析:邻接表中顶点的邻接点是按照插入的先后顺序存储的。

5. 深度优先搜索遍历图的时间复杂度是?A. O(n)B. O(n + e)C. O(n^2)D. O(e)答案:B解析:深度优先搜索遍历图的时间复杂度为O(n + e),其中n 是顶点数,e 是边数。

6. 以下哪种排序算法是稳定的排序算法?A. 快速排序B. 希尔排序C. 冒泡排序D. 选择排序答案:C解析:冒泡排序是稳定的排序算法。

7. 一个具有n 个顶点的无向完全图,其边的数量为?A. n(n - 1) / 2B. n(n - 1)C. n^2D. 2n答案:A解析:无向完全图的边数为n(n - 1) / 2 。

8. 动态规划算法的基本思想是?A. 分治法B. 贪心算法C. 把问题分解成多个子问题并保存子问题的解D. 回溯法答案:C解析:动态规划的基本思想是把问题分解成多个子问题并保存子问题的解,避免重复计算。

9. 以下关于哈希表的说法,错误的是?A. 哈希表的查找时间复杂度为O(1)B. 哈希冲突可以通过开放定址法解决C. 哈希表的空间复杂度是固定的D. 哈希函数的设计会影响哈希表的性能答案:C解析:哈希表的空间复杂度不是固定的,取决于元素数量和负载因子等。

AVL树和红黑树的性能对比和适用场景

AVL树和红黑树的性能对比和适用场景

AVL树和红黑树的性能对比和适用场景AVL树和红黑树都是常用的自平衡二叉查找树,它们在不同的应用场景下具有不同的性能特点。

本文将对AVL树和红黑树的性能进行对比,并分析它们适用的场景。

一、性能对比1. 插入和删除操作AVL树和红黑树在插入和删除操作方面具有不同的性能表现。

由于AVL树要求保持平衡,每次插入或删除操作后都需要进行旋转操作来调整树的平衡。

这样虽然能够保持树的平衡,但是会造成频繁的旋转操作,导致性能较低。

而红黑树则通过颜色标记和旋转操作来保持树的平衡,相比AVL树的旋转操作更少,因此在插入和删除操作方面性能更优。

2. 查找操作在查找操作方面,AVL树和红黑树的性能相当。

它们都保持了二叉查找树的性质,可以在对数时间内完成查找操作。

3. 内存占用由于AVL树要存储额外的平衡信息,每个节点需要额外的一个整数来表示平衡因子,因此相比红黑树来说,AVL树的内存占用更高。

二、适用场景1. 数据插入与删除频繁的场景如果应用场景中涉及频繁的数据插入和删除操作,而对查找操作的性能要求相对较低,则适合选择红黑树。

红黑树通过更少的旋转操作来保持树的平衡,能够在频繁插入和删除操作时,保持较好的性能。

2. 数据查询频繁的场景如果应用场景中涉及频繁的数据查询操作,而对插入和删除操作的性能要求相对较低,则适合选择AVL树。

AVL树由于保持了严格的平衡性,能够在频繁查询操作时,提供更高的查找性能。

3. 对内存占用有限制的场景如果应用场景对内存占用有较严格的限制,则适合选择红黑树。

红黑树相比AVL树的内存占用更低,能够在有限的内存条件下,存储更多的节点。

4. 平衡性要求高且内存占用不是关键问题的场景如果应用场景对平衡性要求较高,而对内存占用没有过多的限制,则AVL树是更好的选择。

AVL树能够保持严格的平衡性,但相对红黑树来说,需要更多的旋转操作,导致性能较低。

三、总结AVL树和红黑树是常用的自平衡二叉查找树,在不同的应用场景下具有不同的性能表现。

太空人平衡树的技巧-概述说明以及解释

太空人平衡树的技巧-概述说明以及解释

太空人平衡树的技巧-概述说明以及解释1.引言1.1 概述太空人平衡树是一种旨在解决二叉搜索树不平衡的问题的数据结构。

它通过使用节点的"权重"来调整树的结构,使得左子树和右子树的高度差尽量小,从而提供更快速的搜索和插入操作。

太空人平衡树的技巧是一套操作和策略,用于在实际应用中有效地构建和维护平衡的树结构。

这些技巧包括节点的旋转、子树的重建以及权重调整等操作。

通过旋转操作,太空人平衡树可以根据特定情况将节点进行左旋或右旋,从而重新构建树的结构。

这样,较高的子树可以通过旋转操作被转移到较低的位置,使得左子树和右子树的高度差得以减小。

另外,当进行插入或删除操作时,太空人平衡树会通过重建子树的方式来调整整个树的平衡。

这意味着,在插入或删除节点时,可能需要将一部分子树重新构建,以保持整个树的平衡状态。

权重调整是太空人平衡树中的一个重要操作,在插入或删除节点后,树的权重可能会发生变化。

通过适时地增加或减少节点的权重,太空人平衡树可以保持树的整体平衡,避免发生不平衡的情况。

总而言之,太空人平衡树的技巧是一种有效解决二叉搜索树不平衡问题的方法。

通过合理地运用节点旋转、子树重建以及权重调整等操作和策略,可以构建出一个高效、平衡的数据结构,提供更快速的搜索和插入操作。

在接下来的文章中,我们将详细介绍太空人平衡树的基本原理以及实际操作技巧。

1.2文章结构本文包括引言、正文和结论等3个子章节。

引言部分概述了太空人平衡树的技巧,并介绍了本文的目的。

正文部分分为两个部分,即基本原理和技巧讲解。

基本原理部分解释了太空人平衡树的基本原理,包括其数据结构和算法等方面的内容。

技巧讲解部分则介绍了太空人平衡树的实际操作技巧,包括如何构建太空人平衡树和应用中的注意事项等。

结论部分总结了太空人平衡树的技巧和应用,以及展望了其未来的发展方向。

通过本文的阅读,读者可以全面了解太空人平衡树的相关知识和在实际应用中的技巧。

1.3 目的本文的目的是探讨太空人平衡树的技巧及其应用。

AVL树及其平衡性

AVL树及其平衡性

AVL树及其平衡性AVL树是一种自平衡的二叉搜索树,它得名于它的发明者Adelson-Velsky和Landis。

AVL树在插入和删除节点时会通过旋转操作来保持树的平衡,以确保树的高度始终保持在一个较小的范围内,从而提高搜索、插入和删除操作的效率。

本文将介绍AVL树的基本概念、特点以及如何保持其平衡性。

一、AVL树的基本概念AVL树是一种二叉搜索树,具有以下特点:1. 每个节点最多有两个子节点,左子节点的值小于父节点的值,右子节点的值大于父节点的值;2. 每个节点都有一个平衡因子(Balance Factor),定义为左子树的高度减去右子树的高度;3. AVL树的平衡因子必须为-1、0或1,即任意节点的左右子树高度差不超过1;4. AVL树中任意节点的左子树和右子树都是AVL树。

二、AVL树的平衡性AVL树通过旋转操作来保持树的平衡,主要包括左旋转、右旋转、左右旋转和右左旋转四种操作。

在插入或删除节点后,如果AVL树的平衡因子不满足要求,就需要进行相应的旋转操作来调整树的结构,以保持平衡性。

1. 左旋转(LL旋转)当某个节点的平衡因子为2,且其左子树的平衡因子为1或0时,需要进行左旋转操作。

左旋转是将当前节点向左旋转,使其右子节点成为新的根节点,原根节点成为新根节点的左子节点,新根节点的左子节点成为原根节点的右子节点。

2. 右旋转(RR旋转)当某个节点的平衡因子为-2,且其右子树的平衡因子为-1或0时,需要进行右旋转操作。

右旋转是将当前节点向右旋转,使其左子节点成为新的根节点,原根节点成为新根节点的右子节点,新根节点的右子节点成为原根节点的左子节点。

3. 左右旋转(LR旋转)当某个节点的平衡因子为2,且其左子树的平衡因子为-1时,需要进行左右旋转操作。

左右旋转是先对当前节点的左子节点进行右旋转,然后再对当前节点进行左旋转。

4. 右左旋转(RL旋转)当某个节点的平衡因子为-2,且其右子树的平衡因子为1时,需要进行右左旋转操作。

C平衡二叉树(AVL)创建和删除

C平衡二叉树(AVL)创建和删除

C平衡⼆叉树(AVL)创建和删除 AVL是最先发明的⾃平衡⼆叉查找树算法。

在AVL中任何节点的两个⼉⼦⼦树的⾼度最⼤差别为⼀,所以它也被称为⾼度平衡树,n个结点的AVL树最⼤深度约1.44log2n。

查找、插⼊和删除在平均和最坏情况下都是O(log n)。

增加和删除可能需要通过⼀次或多次树旋转来重新平衡这个树。

定义 ⽤LH,EH,RH分别表⽰左⼦树⾼,等⾼,右⼦树⾼,即平衡因⼦1、0、-1#include <stdio.h>#include <stdlib.h>#include <stdbool.h>#define LH 1 // 左⾼#define EH 0 // 等⾼#define RH -1 // 右⾼typedef struct TreeNode{int data;int bf;struct TreeNode *left, *right;}TreeNode; 旋转处理 左旋和右旋,记住“左逆右顺”就可以/************************************************* 对以*p为根的⼆叉排序树作右旋处理,处理之后p指向新的树根结点,* A B* / / \* B 旋转后变为 C A* / \ /* C D D* 即旋转处理之前的左⼦树的结点。

************************************************/void r_rotate(TreeNode **p){TreeNode *l = (*p)->left;(*p)->left = l->right;l->right = (*p);*p = l;}/************************************************* 对以*p为根的⼆叉排序树作左旋处理,处理之后p指向新的树根结点,* A B* \ / \* B 旋转后变为 A D* / \ \* C D C* 即旋转处理之前的右⼦树的结点。

二叉树解决问题的方法总结

二叉树解决问题的方法总结

二叉树解决问题的方法
二叉树解决问题的方法可以总结为以下几种:
1. 递归遍历:递归遍历是一种常用的方法,用于遍历二叉树的每个节点。

这种方法通常需要定义一个递归函数,以对每个节点进行操作。

递归遍历可以分为前序遍历、中序遍历和后序遍历。

2. 递归分治:递归分治是一种将问题分解为更小的子问题的方法。

在二叉树中,分治法通常将问题划分为左右两个子问题,并分别解决它们。

递归分治的关键在于如何将问题分解,以及如何合并子问题的解决方案以得到最终答案。

3. 迭代法:迭代法是一种使用循环结构遍历二叉树的方法。

这种方法通常使用堆栈或队列等数据结构来存储节点,以便在循环中进行遍历。

4. 基于BST的查找和插入操作:二叉搜索树(BST)是一种特殊的二叉树,其每个节点的左子树上的所有元素都小于该节点的值,而右子树上的所有元素都大于该节点的值。

基于BST的查找和插入操作可以利用这一性质来快速定位和插入节点。

5. AVL树的插入和删除操作:AVL树是一种自平衡的二叉搜索树,其每个节点的左子树和右子树的高度差不会超过1。

在AVL树中进行插入和删除操作时,需要考虑到如何保持树的平衡,以避免重新平衡操作带来的额外开销。

以上是二叉树解决问题的一些常见方法,具体使用哪种方法取决于问题的性质和要求。

基于选择调整算法的AVL树快速增删算法的研究与实现

基于选择调整算法的AVL树快速增删算法的研究与实现
平 衡 因子 均 为 0 因 此 , 可 以 确 信 : 调 整 后 的 子 树 是 平 衡 , 的 ,如 图4 示 。 所
维普资讯
术 交 流

n2 0

( 、 , )
、 -・,’
pI

p 3
f ) 、—
o o
() “ ” d > 型失衡.
()b(2 )0 f 1< ,b(2 )0 f 1> 2 f 0> 且b( )0 f 0< 且b( )0 p p p p 同理 可得该 情 况下 的结点 平衡 因子 更新策 略 :先按 第一种情况 ,l a的规则 初步确定新平 衡因子,再根据 第  ̄ ) p
l 中


பைடு நூலகம்
一f一 乏 ~ J 胁 一
Pl 3

0 时,不做调 整。失衡子树的高度减少1 。 () f 2 )0 3 b( 0 = p
Po 3
~ ~ 一


我们先视 为:p 1 3 子树 “ 去掉”一层高度, lb(2 )  ̄ f 0 p p 变 为1 1 与b( 1 同号,按 “” 或 “\” 失衡类型进 或一 且 f ) p , 行 结构调整 和初 步确定平 衡 因子 。再看作p 1 3 子树 上 “ 填
、 、 j


’、
、 ~ 一 , -
、 、 j
, ,
除;如果该结点 为单枝 结点, 以其孩子结 点代替其位置, 然后 删 除; 如果该 结 点为 双枝结 点. 则 如果 其平 衡 因子
、 、

一 , -

图4 “0 ,”和 “0 \”型初步调整后再在p 1 3 子树增加一

AVL树与红黑树平衡树的应用与区别

AVL树与红黑树平衡树的应用与区别

AVL树与红黑树平衡树的应用与区别AVL树和红黑树都是常见的自平衡二叉查找树,它们在计算机科学领域中被广泛应用。

本文将探讨AVL树和红黑树的应用及它们之间的区别。

一、AVL树的应用与特点AVL树是一种高度平衡的二叉查找树,它的特点是任意节点的左右子树高度差不超过1。

AVL树通过旋转操作来保持树的平衡,以确保在最坏情况下的查找、插入和删除操作的时间复杂度为O(log n)。

AVL树的应用广泛,特别适用于对插入和删除操作较为频繁的场景,比如数据库索引、编译器中的符号表等。

由于AVL树的严格平衡性,它在某些场景下可能会比红黑树更快,尤其是对于查找操作。

二、红黑树的应用与特点红黑树是一种近似平衡的二叉查找树,它通过引入颜色标记和一些约束条件来保持树的平衡。

红黑树的特点是具有较好的平衡性能,插入和删除操作相对AVL树更为高效,适用于需要频繁插入和删除操作的场景。

红黑树广泛应用于各种编程语言的标准库中,比如C++的STL中的map和set,Java中的TreeMap和TreeSet等。

红黑树的平衡性能虽然不如AVL树那么严格,但在实际应用中往往能够提供更好的性能。

三、AVL树与红黑树的区别1. 平衡性要求不同:AVL树要求任意节点的左右子树高度差不超过1,而红黑树则通过引入颜色标记和约束条件来保持树的近似平衡。

2. 插入和删除操作的效率不同:红黑树在插入和删除操作上比AVL树更高效,因为红黑树的平衡性要求相对宽松,旋转操作相对较少。

3. 查询操作的效率可能有差异:由于AVL树的严格平衡性,它在某些情况下可能比红黑树更快,尤其是对于查找操作。

但在实际应用中,红黑树的性能往往更优秀。

4. 存储空间的利用率不同:由于红黑树的平衡性要求相对宽松,它在存储空间利用率上可能比AVL树更好,因为红黑树的高度不会像AVL树那样严格受限。

综上所述,AVL树和红黑树都是重要的平衡树结构,在不同的应用场景下有着各自的优势和特点。

AVL树了解AVL树的平衡性和旋转操作

AVL树了解AVL树的平衡性和旋转操作

AVL树了解AVL树的平衡性和旋转操作AVL树,全称Adelson-Velsky-Landis树,是一种经典的自平衡二叉搜索树。

在AVL树中,任意节点的左子树和右子树的高度差不超过1,这保证了树的平衡性。

为了维持平衡,AVL树在插入和删除节点时,会通过旋转操作来调整树的结构。

下面我们将了解AVL树的平衡性以及旋转操作的原理和步骤。

一、AVL树的平衡性AVL树的平衡性是指树的任意节点的左子树和右子树的高度差不超过1。

为了实现这种平衡性,AVL树的节点需要存储每个子树的高度信息,并在插入和删除节点时,通过旋转操作来调整树的结构,以维持平衡。

二、旋转操作的原理和步骤旋转操作是AVL树用来调整结构的主要方法,分为左旋和右旋两种。

下面我们将详细介绍这两种旋转操作的原理和步骤。

1. 左旋左旋操作是指将当前节点的右子节点上移,当前节点成为新的左子节点。

左旋操作的原理如下:(1)将当前节点的右子节点的左子节点作为当前节点的右子节点;(2)将当前节点的右子节点作为新的根节点;(3)将当前节点作为右子节点的左子节点。

左旋操作的步骤如下:(1)判断当前节点是否有右子节点,若没有,则无法进行左旋操作;(2)保存当前节点的右子节点,并将右子节点的左子节点设置为当前节点的右子节点;(3)将当前节点的右子节点设为右子节点的左子节点;(4)将右子节点设为当前节点的左子节点;(5)更新当前节点和右子节点的高度信息。

2. 右旋右旋操作是指将当前节点的左子节点上移,当前节点成为新的右子节点。

右旋操作的原理如下:(1)将当前节点的左子节点的右子节点作为当前节点的左子节点;(2)将当前节点的左子节点作为新的根节点;(3)将当前节点作为左子节点的右子节点。

右旋操作的步骤如下:(1)判断当前节点是否有左子节点,若没有,则无法进行右旋操作;(2)保存当前节点的左子节点,并将左子节点的右子节点设置为当前节点的左子节点;(3)将当前节点的左子节点设为左子节点的右子节点;(4)将左子节点设为当前节点的右子节点;(5)更新当前节点和左子节点的高度信息。

实验报告

实验报告

哈尔滨工业大学计算机科学与技术学院实验报告课程名称:数据结构与算法课程类型:必修实验项目名称:A VL树实验题目:A VL树班级:0836001学号:6080310126姓名:赵文博一、实验目的通过编写实现AVL树的各种功能,熟悉AVL树的原理与使用方法。

二、实验要求及实验环境要求:1.具有插入(建立)、删除和查找功能2.插入操作应包括四种类型的平衡化处理3.删除操作应包括四种类型的平衡化处理并且包括多次平衡化处理4.能体现操作前后二叉树的形态及其变化实验环境:IDE:Codeblocks 8.0.2系统:windows XP语言: C++三、设计思想所使用的变量与函数:struct node //A VL树中的节点{int height, data;node *left, *right;};node *root; //根节点int ret(node *po) //返回一个节点的height值,若节点为空返回0void rotateLL(node* &r) //LL旋转void rotateRR(node* &r) //RR旋转void rotateRL(node* &r) //RL旋转void rotateLR(node* &r) //LR旋转void insert(node* &p, int number) //插入这里未使用平衡因子,而是使用高度代替void rotateDelete(node* &p) //删除时的旋转void Delete(node* &p, int data) //删除元素int search(node* &p, int x) //查找元素void show(node* &p) //输出A VL树中的所有元素流程图:四、测试结果按如下顺序插入元素,不断的输出A VL树的结构:1 3 2 5 6 4 9 8 71:数据: [1] 左节点: NULL 右节点: NULL3:数据: [1] 左节点: NULL 右节点: [3]数据: [3] 左节点: NULL 右节点: NULL2:数据: [2] 左节点: [1] 右节点: [3]数据: [1] 左节点: NULL 右节点: NULL数据: [3] 左节点: NULL 右节点: NULL5:数据: [2] 左节点: [1] 右节点: [3]数据: [1] 左节点: NULL 右节点: NULL数据: [3] 左节点: NULL 右节点: [5]数据: [5] 左节点: NULL 右节点: NULL6:数据: [2] 左节点: [1] 右节点: [5]数据: [1] 左节点: NULL 右节点: NULL数据: [5] 左节点: [3] 右节点: [6]数据: [3] 左节点: NULL 右节点: NULL数据: [6] 左节点: NULL 右节点: NULL4:数据: [3] 左节点: [2] 右节点: [5]数据: [2] 左节点: [1] 右节点: NULL数据: [1] 左节点: NULL 右节点: NULL数据: [5] 左节点: [4] 右节点: [6]数据: [4] 左节点: NULL 右节点: NULL数据: [6] 左节点: NULL 右节点: NULL9:数据: [3] 左节点: [2] 右节点: [5]数据: [2] 左节点: [1] 右节点: NULL数据: [1] 左节点: NULL 右节点: NULL 数据: [5] 左节点: [4] 右节点: [6]数据: [4] 左节点: NULL 右节点: NULL 数据: [6] 左节点: NULL 右节点: [9]数据: [9] 左节点: NULL 右节点: NULL 8:数据: [3] 左节点: [2] 右节点: [5]数据: [2] 左节点: [1] 右节点: NULL数据: [1] 左节点: NULL 右节点: NULL 数据: [5] 左节点: [4] 右节点: [8]数据: [4] 左节点: NULL 右节点: NULL 数据: [8] 左节点: [6] 右节点: [9]数据: [6] 左节点: NULL 右节点: NULL 数据: [9] 左节点: NULL 右节点: NULL 7:数据: [3] 左节点: [2] 右节点: [6]数据: [2] 左节点: [1] 右节点: NULL数据: [1] 左节点: NULL 右节点: NULL 数据: [6] 左节点: [5] 右节点: [8]数据: [5] 左节点: [4] 右节点: NULL数据: [4] 左节点: NULL 右节点: NULL 数据: [8] 左节点: [7] 右节点: [9]数据: [7] 左节点: NULL 右节点: NULL 数据: [9] 左节点: NULL 右节点: NULL随后,删除1,7,31数据: [3] 左节点: [2] 右节点: [6]数据: [2] 左节点: NULL 右节点: NULL 数据: [6] 左节点: [5] 右节点: [8]数据: [5] 左节点: [4] 右节点: NULL数据: [4] 左节点: NULL 右节点: NULL 数据: [8] 左节点: [7] 右节点: [9]数据: [7] 左节点: NULL 右节点: NULL 数据: [9] 左节点: NULL 右节点: NULL 7:数据: [3] 左节点: [2] 右节点: [6]数据: [2] 左节点: NULL 右节点: NULL 数据: [6] 左节点: [5] 右节点: [8]数据: [5] 左节点: [4] 右节点: NULL数据: [4] 左节点: NULL 右节点: NULL数据: [8] 左节点: NULL 右节点: [9]数据: [9] 左节点: NULL 右节点: NULL3数据: [4] 左节点: [2] 右节点: [6]数据: [2] 左节点: NULL 右节点: NULL数据: [6] 左节点: [5] 右节点: [8]数据: [5] 左节点: NULL 右节点: NULL数据: [8] 左节点: NULL 右节点: [9]数据: [9] 左节点: NULL 右节点: NULL此时,查找元素2 5 102,5返回找到10返回未找到。

avl方案介绍

avl方案介绍

avl方案1. 引言AVL树是一种自平衡二叉查找树,它在操作过程中保持树的高度平衡,从而保证了各种基本操作的时间复杂度为O(log n)。

本文将介绍AVL树的原理、实现方法以及应用场景。

2. AVL树的原理AVL树是由G.M. Adelson-Velsky和E.M. Landis在1962年提出的,它的名称取自于他们的名字的首字母。

AVL树的特点是每个节点的左子树和右子树的高度差不超过1,即保证了树的高度平衡。

AVL树的插入和删除操作会导致树的失衡,为了维持树的平衡,AVL树使用了旋转操作。

旋转操作主要包括左旋和右旋,通过重新调整子树的结构来使得树重新达到平衡。

3. 实现AVL树实现AVL树可以采用递归或迭代的方式,这里以递归方式为例进行说明。

3.1 AVL树节点定义首先需要定义AVL树的节点结构,一个简单的AVL树节点可以包括以下几个字段:class AVLNode:def__init__(self, key):self.key = keyself.left =Noneself.right =Noneself.height =1其中,key字段用于存储节点的键值,left和right字段分别指向节点的左子树和右子树,height字段表示节点的高度。

3.2 AVL树的插入操作AVL树的插入操作分为以下几个步骤:1.找到插入位置,若树为空,则直接插入新节点。

2.根据插入节点的键值与当前节点的键值进行比较,决定向左子树或右子树递归插入。

行旋转操作。

4.若当前节点失衡,根据失衡情况选择合适的旋转操作进行平衡调整。

下面是插入操作的递归实现代码:def insert(root, key):if not root:return AVLNode(key)elif key < root.key:root.left = insert(root.left, key)else:root.right = insert(root.right, key)root.height =1+ max(get_height(root.left), get_height(root.right)) balance = get_balance(root)# 左旋if balance >1and key < root.left.key:return rotate_right(root)# 右旋if balance <-1and key > root.right.key:return rotate_left(root)# 左右旋if balance >1and key > root.left.key:root.left = rotate_left(root.left)return rotate_right(root)# 右左旋if balance <-1and key < root.right.key:root.right = rotate_right(root.right)return rotate_left(root)return root3.3 AVL树的删除操作AVL树的删除操作也需要进行树的平衡调整,它分为以下几个步骤:1.找到待删除的节点。

课题_一步一步写平衡二叉树(AVL树)

课题_一步一步写平衡二叉树(AVL树)

一步一步写平衡二叉树(AVL树)平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树。

1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树。

平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态。

这个方案很好的解决了二叉查找树退化成链表的问题,把插入、查找、删除的时间复杂度最好情况和最坏情况都维持在O(logN)。

但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

平衡二叉树实现的大部分过程和二叉查找树是一样的(学平衡二叉树之前一定要会二叉查找树),区别就在于插入和删除之后要写一个旋转算法去维持平衡,维持平衡需要借助一个节点高度的属性。

我参考了机械工业出版社的《数据结构与算法分析- C语言描述》写了一个C++版的代码。

这本书的AVLTree讲的很好,不过没有很完整的去描述。

我会一步一步的讲解如何写平衡二叉树,重点是平衡二叉树的核心部分,也就是旋转算法。

第一步:节点信息相对于二叉查找树的节点来说,我们需要用一个属性表示二叉树的高度,目的是维护插入和删除过程中的旋转算法。

代码如下://AVL树节点信息template<class T>class TreeNode{public:TreeNode():lson(NULL),rson(NULL),freq(1),hgt(0){}T data;//值int hgt;//以此节点为根的树的高度unsigned int freq;//频率TreeNode* lson;//指向左儿子的地址TreeNode* rson;//指向右儿子的地址};第二步:平衡二叉树(AVL)类的声明声明中的旋转函数将在后边的步骤中详解。

AVL树的平衡策略

AVL树的平衡策略

AVL树的平衡策略AVL树是一种自平衡二叉搜索树,通过保持树的左右子树的高度差在指定范围内来维持平衡。

在本文中,我们将介绍AVL树的平衡策略以及它的实现。

一、AVL树的介绍AVL树是一种二叉搜索树,它的每个节点都包含一个额外的平衡因子,即该节点的左子树和右子树的高度差。

平衡因子可以是 -1、0 或 1,当平衡因子的绝对值超过1时,树就不再平衡,需要通过旋转操作进行调整。

二、插入操作在AVL树中插入一个节点时,首先进行二叉搜索树的插入操作。

接着,从插入节点的父节点开始向上回溯,更新每个祖先节点的平衡因子。

如果某个祖先节点的平衡因子超过了1,即左子树高度大于右子树,或者小于-1,即右子树高度大于左子树,那么就需要进行相应的旋转操作来恢复平衡。

三、旋转操作AVL树的旋转操作包括左旋和右旋。

左旋是指将当前节点的右子树提升为新的根节点,当前节点成为新根节点的左子树。

右旋则是相反的操作,将当前节点的左子树提升为新的根节点,当前节点成为新根节点的右子树。

四、平衡调整在进行插入操作后,AVL树可能会失去平衡,而需要进行相应的平衡调整。

平衡调整可以通过不同类型的旋转操作来实现,包括左旋、右旋、左右旋和右左旋等。

1. 左旋:当插入节点导致某个祖先节点的平衡因子为2,并且插入节点在该祖先节点的左子树的左子树上时,进行左旋操作。

2. 右旋:当插入节点导致某个祖先节点的平衡因子为-2,并且插入节点在该祖先节点的右子树的右子树上时,进行右旋操作。

3. 左右旋:当插入节点导致某个祖先节点的平衡因子为2,并且插入节点在该祖先节点的左子树的右子树上时,先对插入节点的左子树进行一次右旋操作,然后对祖先节点进行左旋操作。

4. 右左旋:当插入节点导致某个祖先节点的平衡因子为-2,并且插入节点在该祖先节点的右子树的左子树上时,先对插入节点的右子树进行一次左旋操作,然后对祖先节点进行右旋操作。

五、删除操作在AVL树中删除一个节点时,首先进行二叉搜索树的删除操作。

数据结构AV树

数据结构AV树

二叉搜索树的结构定义
typedef struct node { KeyType key ; /*关键字的值 关键字的值*/ 关键字的值 int bf; //结点平衡因子 ; 结点平衡因子 struct node *lchild,*rchild;/*左右指针 左右指针*/ 左右指针 struct node * parent; //父结点指针 }bstnode,*BSTree;
如果在某一结点发现高度不平衡,停止回 如果在某一结点发现高度不平衡, 从发生不平衡的结点起, 溯。从发生不平衡的结点起,沿刚才回溯 的路径取直接下两层的结点。 的路径取直接下两层的结点。 如果这三个结点处于一条直线上,则采用 如果这三个结点处于一条直线上, 单旋转进行平衡化。 单旋转进行平衡化。单旋转可按其方向分 LL旋转和 旋转 旋转和RR旋转, 为LL旋转和RR旋转, 其中一个是另一 个 的镜像,其方向与不平衡的形状相关。 的镜像,其方向与不平衡的形状相关。 如果这三个结点处于一条折线上, 如果这三个结点处于一条折线上,则采用 双旋转进行平衡化。双旋转分为LR旋转和 双旋转进行平衡化。双旋转分为LR旋转和 RL旋转两类 RL旋转两类。 旋转两类。
AVL树 AVL树 的重要性质
• 含有n个结点的AVL树的高度为O(log n); AVL树的高度为 1. 含有n个结点的AVL树的高度为O(log2n); • 在含有n个结点的AVL AVL树中搜索一个元素需要为 2. 在含有n个结点的AVL树中搜索一个元素需要为 n)时间 时间; O(log2n)时间; • 将一个新元素插入一棵n个结点的AVL树中, AVL树中 3. 将一个新元素插入一棵n个结点的AVL树中,可得 到一棵n+1个结点的AVL n+1个结点的AVL树 且插入所需的时间为O(log n); 到一棵n+1个结点的AVL树,且插入所需的时间为O(log2n); • 4. 从一棵n个结点的AVL树删除一个元素,可得到一 从一棵n个结点的AVL树删除一个元素, AVL树删除一个元素 个结点的AVL AVL树 且删除所需的时间为O(log n); 棵n-1个结点的AVL树,且删除所需的时间为O(log2n);
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

AVL树插入删除
AVL树是一种平衡二叉树,其每个节点的左右子树高度最多差1,空树高度定为-1,当左右的高度超过1,即失去了平衡,不是AVL树了。

private static class AVLNode<AnyType>{
AVLNode (AnyType element)
{this(element ,null,null);}
AVLNode(AnyTape element,AVLNode<AnyType> left,AVLNode<AnyType> right){
this.element = element;
this.left = left;
this.right = right;
}
AnyTape element;
AVLNode<AnyType> left;
AVLNode<AnyType> right;
int height;
}
这是AVL树的节点声明,声明了节点,左右子树以及高度。

在进行插入和删除操作时可能会使AVL树左右子树的高度相差超过1,破坏了平衡,当平衡破坏时,在插入或删除完成前恢复平衡要进行旋转。

旋转分为单旋转和双旋转。

把必须重新平衡的节点叫做t,下面是单旋转和双旋转的情况。

1.对于t的左儿子的左子树进行插入->单旋转
2.对于t的左儿子的右子树进行插入->双旋转
3.对于t的右儿子的左子树进行插入->双旋转
4.对于t的右儿子的右子树进行插入->单旋转
由此总结,左-左,右-右是单旋转,左-右,右-左是双旋转
在旋转之前,插一下节点高度计算
private int height(AVLNode<AnyType> t){
return t == null ? -1 : t.height;
}
1.左-左:单旋
private AVLNode<AnyType> rotateLeftChild(AVLNode<AnyType> k1){ AVLNode<AnyType> k2 = k1.right;
k1.right = k2.left;
k1.height = Maht.max(height(k1.left),height(k1.right))+1; k1.height = Maht.max(height(k2.right),k1.height)+1;
return k2;
}
2.左-右:双旋转
private AVLNode<AnyType> doubleLeftChild(AVLNode<AnyType> k3){ k3.left = rotateReft(k3.left);
return rotateLeft(k3);
}
3.右-左:双旋转
private AVLNode<AnyType> doubleRightChild(AVLNode<AnyType> k3){
k3.right = rotateLeftChild(k3.right);
return rotateRightChild(k3);
}
4.右-右:单旋
private AVLNode<AnyType> rotateRightChild(AVLNode<AnyType> k2){
AVLNode<AnyType> k1 = k2.left;
k2.left = k1.right;
k2.height = Maht.max(height(k2.left),height(k2.right))+1;
k1.height = Maht.max(height(k1.left),k2.height)+1;
return k1;
}
说完了旋转,接下来就是插入操作了
private AVLNode<AnyType> insert(AnyType x,AVLNode<AnyType>t){
if(t == null)
return new AVLNode<>(x,null,null);
int result = pareTo(t.element);
if( result < 0) //如果X小于节点值,则在左子树插入,递归更新
t.left = insert(x,t.left);
else if( result > 0) //如果X大于节点值,则在右子树插入,递归 t.right = insert(x,t.right);
return balance(t);
}
private static final int balance_num = 1;
private AVLNode<AnyType> balance(AVLNode<AnyType>t){
if(t == null)
return t;
if(height(t.left) - height(right) > balance_num){
if(height(t.left.left) > height(t.left.right)) //左-左
t = rotateLeftChild(t);
else
t = doubleLeftChild(t); //左-右
}else{
if(height(t.right.right) > height(t.right.left)) //右-左 t = rotateRightChild(t);
else
t = doubleRightChild(t); //右-左
}
t.height = Math.max(height(t.left),height(t.right))+1;
return t;
}
旋转一定要保持平衡,所以要返回的是balance(t)而不是t。

接下来进行删除操作,删除较插入更为复杂。

private AVLNode<AnyType> remove(AnyType x,AVLNode<AnyType>t){
if(t == null)
return new AVLNode<>(x,null,null);
int result = pareTo(t.element);
if( result < 0) //如果X小于节点值,则在左子树删除,递归更新
t.left = insert(x,t.left);
else if( result > 0) //如果X大于节点值,则在右子树删除,递归 t.right = insert(x,t.right);
else if(t.left != null && t.right != null){
t.element = findMin(t.right).element; //找到右子树最小值 t.right = remove(t.element,t.right) //删除右子树最小值原来的位置
}
else
t = (t.left != null)?t.left:t.right; //如果是一个儿子或者没有,哪个儿子不为空就返回哪个儿子
return balance(t);
}
总体来说删除操作和二叉搜索树的想法包括代码都几乎是一致的,但是重要不同的一点就是AVL树需要进行旋转重平衡。

理解了旋转就基本上插入删除思路想法和二叉搜索都一致。

相关文档
最新文档