目录
代码出处
各种实现
概念说明
算法说明
测试运行
代码修改
完整源码
代码出处
各种实现
- Java实现
Data Structures and Algorithm Analysis in Java (Third Edition)
CS-7 Text
https://users.cs.fiu.edu/~weiss/dsaajava3/code/
https://users.cs.fiu.edu/~weiss/dsaajava3/code/AvlTree.java
- C++11
Data Structures and Algorithm Analysis in C++ (Fourth Edition)
CS-7 Text
https://users.cs.fiu.edu/~weiss/dsaa_c++4/code/
g++ -std=c++0x TestAvlTree.cpp
g++ -std=c++0x TestIntCell.cpp IntCell.cpp
AvlTree.h: AVL tree
TestAvlTree.cpp: Test program for AVL trees
- C
Data Structures and Algorithm Analysis in C (Second Edition)
CS-7 Text
https://users.cs.fiu.edu/~weiss/dsaa_c2e/files.html
avltree.h: Header file for AVL tree
avltree.c: Implementation for AVL tree
testavl.c: Test program for AVL trees
概念说明
AVL树
https://en.wikipedia.org/wiki/AVL_tree
In an AVL tree, the heights of the two child subtrees of any node differ by at most one
在AVL树种,任意两棵子树的高度不能超过1;
路径 path
、长度 length
、 高度height
与 深度depth
The root node has depth zero, leaf nodes have height zero.
根结点的深度是0
,叶子结点的高度是0
;
路径 path
从结点n1到结点nk的路径是,一路上的结点序列 n1 n2 ... nk
长度 length
路径的长度,是指这条路径上,经过的边数
高度height 与 深度depth
结点nk的深度depth,是从根结点到nk结点的路径(即结点序列);
结点nk的高度height,是从nk结点到叶结点的最长路径;
叶结点的高度是0,根结点的深度是0;
- 要求某个结点的高度
height
,要往下走down
,找叶子结点leaf
; - 要求某个结点的深度
depth
,要往上走up
,找根结点root
;
算法说明
流程
-
insert()
以BST
的插入规则新增结点; -
insert()
最后return balance( t );
,调用balance()
,完成AVL的平衡; -
balance()
4种case,进行相应的旋转; - 一次插入,只需要进行一次平衡(一次单旋或者一次双旋),树就会重新回到平衡状态;
- 一次删除,可能会朝着祖先结点一直蔓延上去,最多需要调整平衡
logn
次;
单旋
Figure 4.31 Single rotation to fix case 1
-
height( t.left.left ) >= height( t.left.right )
Figure 4.31 Single rotation to fix case 1
private AvlNode<AnyType> rotateWithLeftChild( AvlNode<AnyType> k2 )
{
AvlNode<AnyType> k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max( height( k2.left ), height( k2.right ) ) + 1;
k1.height = Math.max( height( k1.left ), k2.height ) + 1;
return k1;
}
Figure 4.33 Single rotation fixes case 4
-
height( t.right.right ) >= height( t.right.left )
Figure 4.33 Single rotation fixes case 4
private AvlNode<AnyType> rotateWithRightChild( AvlNode<AnyType> k1 )
{
AvlNode<AnyType> k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max( height( k1.left ), height( k1.right ) ) + 1;
k2.height = Math.max( height( k2.right ), k1.height ) + 1;
return k2;
}
双旋
Figure 4.34 Single rotation fails to fix case 2
Figure 4.34 Single rotation fails to fix case 2Figure 4.35 Left–right double rotation to fix case 2
-
height( t.left.left) < height( t.left.right )
Figure 4.35 Left–right double rotation to fix case 2
private AvlNode<AnyType> doubleWithLeftChild( AvlNode<AnyType> k3 )
{
k3.left = rotateWithRightChild( k3.left );
return rotateWithLeftChild( k3 );
}
Figure 4.36 Right–left double rotation to fix case 3
-
height( t.right.right ) < height( t.right.left )
Figure 4.36 Right–left double rotation to fix case 3
private AvlNode<AnyType> doubleWithRightChild( AvlNode<AnyType> k1 )
{
k1.right = rotateWithLeftChild( k1.right );
return rotateWithRightChild( k1 );
}
感想
- 平衡操作是伴随着树的生长同步进行的,插一个结点就要做一次平衡,而不是先构建好一整棵树再去平衡,我觉得AVL树更像是一种从下往上叠着长出来的结构 ,而不是第一眼所见那种纵深向下的结构,因此,从整棵树的生命来看,的确就是在从下往上地做平衡;
- 单旋,本质就是一些链表重新连接;
- 双旋,站在一次单旋算作一个动作的抽象高度上,人脑处理双旋其实更倾向于感觉没什么旋转,无非是找到当新根的k2,左孩子一定是k1,右孩子一定是k3,剩余各部分依次填好即可,然而,对应的实现里,本质却是两次旋转;
- 双旋内部的第一次旋转,其实不会改变整棵树的平衡,更准确的说是,转了这一次,树还是失衡的,但是这一次旋转本质上却达到了顺利把失衡的case从2,3变成了1,4,
左右左→左左左
右左右→右右右
,这种思想叫做规约,遇到新问题不能一步解决,就先把新问题转换成老问题,之后老问题就可以用老方法干掉了; - 双旋代码实现的精妙之处在于,不仅仅老办法是单旋,甚至连转换也是用的单旋,而如果只孤立地看转换用的第一次单旋,会觉得这有何用,无济于事等等,事实上,事情上这时候距离完成全部的平衡就是临门一脚了。
测试运行
- 至少需要
Requires Java 7.
- 源码:
AvlTree.java
以及UnderflowException.java
(官网完整源码包) - 编译运行输出:每插入一个结点
node[i]
,就以先序序列输出当前的AVL树,这里展示最后一次输出;
> javac AvlTree.java
> java AvlTree
INSERT: 9
7
4
2
1
3
6
5
13
11
9
8
10
12
15
14
16
- 如何读?从上而下,从左而右,以缩进判断层次,类似文件目录;
- 对应的AVL树示意图:
image.png - 小BUG:其实仅仅从输出来看,的确是无法判断结点5是结点6的哪个孩子的,但是这仅仅是自己写的输出部分的BUG,不重要,暂时不进行优化;
代码修改:对AvlTree.java
进行以下两处修改
- 修改
main()
函数测试代码,指定一组结点依次插入;
// Test program
public static void main( String [ ] args )
{
AvlTree<Integer> t = new AvlTree<>( );
int[] nodes = {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
for( int i = 0; i < nodes.length; i++ )
{
System.out.println( "INSERT: " + nodes[i] );
t.insert( nodes[i] );
t.preorder();
}
}
- 新增
preorder()
相关:前序序列输出AVL树,带空格表示层次结构
/**
* Print the tree contents in preorder.
*/
public void preorder()
{
if( isEmpty() )
System.out.println( "Empty tree" );
else
preorder( root , 0 );
System.out.println();
}
/**
* Internal method to print a subtree in preorder.
* @param t the node that roots the tree.
*/
private void preorder( AvlNode<AnyType> t, int blanks)
{
if( t != null )
{
System.out.println();
for(int i = 0 ;i < blanks; i++)
System.out.print(" ");
System.out.print( t.element );
preorder( t.left, blanks+1 );
preorder( t.right, blanks+1 );
}
}
完整源码 AvlTree.java
// AvlTree class
//
// CONSTRUCTION: with no initializer
//
// ******************PUBLIC OPERATIONS*********************
// void insert( x ) --> Insert x
// void remove( x ) --> Remove x (unimplemented)
// boolean contains( x ) --> Return true if x is present
// boolean remove( x ) --> Return true if x was present
// Comparable findMin( ) --> Return smallest item
// Comparable findMax( ) --> Return largest item
// boolean isEmpty( ) --> Return true if empty; else false
// void makeEmpty( ) --> Remove all items
// void printTree( ) --> Print tree in sorted order
// ******************ERRORS********************************
// Throws UnderflowException as appropriate
/**
* Implements an AVL tree.
* Note that all "matching" is based on the compareTo method.
* @author Mark Allen Weiss
*/
public class AvlTree<AnyType extends Comparable<? super AnyType>>
{
/**
* Construct the tree.
*/
public AvlTree( )
{
root = null;
}
/**
* Insert into the tree; duplicates are ignored.
* @param x the item to insert.
*/
public void insert( AnyType x )
{
root = insert( x, root );
}
/**
* Remove from the tree. Nothing is done if x is not found.
* @param x the item to remove.
*/
public void remove( AnyType x )
{
root = remove( x, root );
}
/**
* Internal method to remove from a subtree.
* @param x the item to remove.
* @param t the node that roots the subtree.
* @return the new root of the subtree.
*/
private AvlNode<AnyType> remove( AnyType x, AvlNode<AnyType> t )
{
if( t == null )
return t; // Item not found; do nothing
int compareResult = x.compareTo( t.element );
if( compareResult < 0 )
t.left = remove( x, t.left );
else if( compareResult > 0 )
t.right = remove( x, t.right );
else if( t.left != null && t.right != null ) // Two children
{
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 );
}
/**
* Find the smallest item in the tree.
* @return smallest item or null if empty.
*/
public AnyType findMin( )
{
if( isEmpty( ) )
throw new UnderflowException( );
return findMin( root ).element;
}
/**
* Find the largest item in the tree.
* @return the largest item of null if empty.
*/
public AnyType findMax( )
{
if( isEmpty( ) )
throw new UnderflowException( );
return findMax( root ).element;
}
/**
* Find an item in the tree.
* @param x the item to search for.
* @return true if x is found.
*/
public boolean contains( AnyType x )
{
return contains( x, root );
}
/**
* Make the tree logically empty.
*/
public void makeEmpty( )
{
root = null;
}
/**
* Test if the tree is logically empty.
* @return true if empty, false otherwise.
*/
public boolean isEmpty( )
{
return root == null;
}
/**
* Print the tree contents in sorted order.
*/
public void printTree( )
{
if( isEmpty( ) )
System.out.println( "Empty tree" );
else
printTree( root );
}
/**
* Print the tree contents in preorder.
*/
public void preorder()
{
if( isEmpty() )
System.out.println( "Empty tree" );
else
preorder( root , 0 );
System.out.println();
}
private static final int ALLOWED_IMBALANCE = 1;
// Assume t is either balanced or within one of being balanced
private AvlNode<AnyType> balance( AvlNode<AnyType> t )
{
if( t == null )
return t;
if( height( t.left ) - height( t.right ) > ALLOWED_IMBALANCE )
if( height( t.left.left ) >= height( t.left.right ) )
t = rotateWithLeftChild( t );
else
t = doubleWithLeftChild( t );
else
if( height( t.right ) - height( t.left ) > ALLOWED_IMBALANCE )
if( height( t.right.right ) >= height( t.right.left ) )
t = rotateWithRightChild( t );
else
t = doubleWithRightChild( t );
t.height = Math.max( height( t.left ), height( t.right ) ) + 1;
return t;
}
public void checkBalance( )
{
checkBalance( root );
}
private int checkBalance( AvlNode<AnyType> t )
{
if( t == null )
return -1;
if( t != null )
{
int hl = checkBalance( t.left );
int hr = checkBalance( t.right );
if( Math.abs( height( t.left ) - height( t.right ) ) > 1 ||
height( t.left ) != hl || height( t.right ) != hr )
System.out.println( "OOPS!!" );
}
return height( t );
}
/**
* Internal method to insert into a subtree.
* @param x the item to insert.
* @param t the node that roots the subtree.
* @return the new root of the subtree.
*/
private AvlNode<AnyType> insert( AnyType x, AvlNode<AnyType> t )
{
if( t == null )
return new AvlNode<>( x, null, null );
int compareResult = x.compareTo( t.element );
if( compareResult < 0 )
t.left = insert( x, t.left );
else if( compareResult > 0 )
t.right = insert( x, t.right );
else
; // Duplicate; do nothing
return balance( t );
}
/**
* Internal method to find the smallest item in a subtree.
* @param t the node that roots the tree.
* @return node containing the smallest item.
*/
private AvlNode<AnyType> findMin( AvlNode<AnyType> t )
{
if( t == null )
return t;
while( t.left != null )
t = t.left;
return t;
}
/**
* Internal method to find the largest item in a subtree.
* @param t the node that roots the tree.
* @return node containing the largest item.
*/
private AvlNode<AnyType> findMax( AvlNode<AnyType> t )
{
if( t == null )
return t;
while( t.right != null )
t = t.right;
return t;
}
/**
* Internal method to find an item in a subtree.
* @param x is item to search for.
* @param t the node that roots the tree.
* @return true if x is found in subtree.
*/
private boolean contains( AnyType x, AvlNode<AnyType> t )
{
while( t != null )
{
int compareResult = x.compareTo( t.element );
if( compareResult < 0 )
t = t.left;
else if( compareResult > 0 )
t = t.right;
else
return true; // Match
}
return false; // No match
}
/**
* Internal method to print a subtree in sorted order.
* @param t the node that roots the tree.
*/
private void printTree( AvlNode<AnyType> t )
{
if( t != null )
{
printTree( t.left );
System.out.println( t.element );
printTree( t.right );
}
}
/**
* Internal method to print a subtree in preorder.
* @param t the node that roots the tree.
*/
private void preorder( AvlNode<AnyType> t, int blanks)
{
if( t != null )
{
System.out.println();
for(int i = 0 ;i < blanks; i++)
System.out.print(" ");
System.out.print( t.element );
preorder( t.left, blanks+1 );
preorder( t.right, blanks+1 );
}
}
/**
* Return the height of node t, or -1, if null.
*/
private int height( AvlNode<AnyType> t )
{
return t == null ? -1 : t.height;
}
/**
* Rotate binary tree node with left child.
* For AVL trees, this is a single rotation for case 1.
* Update heights, then return new root.
*/
private AvlNode<AnyType> rotateWithLeftChild( AvlNode<AnyType> k2 )
{
AvlNode<AnyType> k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max( height( k2.left ), height( k2.right ) ) + 1;
k1.height = Math.max( height( k1.left ), k2.height ) + 1;
return k1;
}
/**
* Rotate binary tree node with right child.
* For AVL trees, this is a single rotation for case 4.
* Update heights, then return new root.
*/
private AvlNode<AnyType> rotateWithRightChild( AvlNode<AnyType> k1 )
{
AvlNode<AnyType> k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max( height( k1.left ), height( k1.right ) ) + 1;
k2.height = Math.max( height( k2.right ), k1.height ) + 1;
return k2;
}
/**
* Double rotate binary tree node: first left child
* with its right child; then node k3 with new left child.
* For AVL trees, this is a double rotation for case 2.
* Update heights, then return new root.
*/
private AvlNode<AnyType> doubleWithLeftChild( AvlNode<AnyType> k3 )
{
k3.left = rotateWithRightChild( k3.left );
return rotateWithLeftChild( k3 );
}
/**
* Double rotate binary tree node: first right child
* with its left child; then node k1 with new right child.
* For AVL trees, this is a double rotation for case 3.
* Update heights, then return new root.
*/
private AvlNode<AnyType> doubleWithRightChild( AvlNode<AnyType> k1 )
{
k1.right = rotateWithLeftChild( k1.right );
return rotateWithRightChild( k1 );
}
private static class AvlNode<AnyType>
{
// Constructors
AvlNode( AnyType theElement )
{
this( theElement, null, null );
}
AvlNode( AnyType theElement, AvlNode<AnyType> lt, AvlNode<AnyType> rt )
{
element = theElement;
left = lt;
right = rt;
height = 0;
}
AnyType element; // The data in the node
AvlNode<AnyType> left; // Left child
AvlNode<AnyType> right; // Right child
int height; // Height
}
/** The tree root. */
private AvlNode<AnyType> root;
// Test program
public static void main( String [ ] args )
{
AvlTree<Integer> t = new AvlTree<>( );
int[] nodes = {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
for( int i = 0; i < nodes.length; i++ )
{
System.out.println( "INSERT: " + nodes[i] );
t.insert( nodes[i] );
t.preorder();
}
}
}
完整源码 TestAvlTree.cpp
#ifndef AVL_TREE_H
#define AVL_TREE_H
#include "dsexceptions.h"
#include <algorithm>
#include <iostream>
using namespace std;
// AvlTree class
//
// CONSTRUCTION: zero parameter
//
// ******************PUBLIC OPERATIONS*********************
// void insert( x ) --> Insert x
// void remove( x ) --> Remove x (unimplemented)
// bool contains( x ) --> Return true if x is present
// Comparable findMin( ) --> Return smallest item
// Comparable findMax( ) --> Return largest item
// boolean isEmpty( ) --> Return true if empty; else false
// void makeEmpty( ) --> Remove all items
// void printTree( ) --> Print tree in sorted order
// ******************ERRORS********************************
// Throws UnderflowException as warranted
template <typename Comparable>
class AvlTree
{
public:
AvlTree( ) : root{ nullptr }
{ }
AvlTree( const AvlTree & rhs ) : root{ nullptr }
{
root = clone( rhs.root );
}
AvlTree( AvlTree && rhs ) : root{ rhs.root }
{
rhs.root = nullptr;
}
~AvlTree( )
{
makeEmpty( );
}
/**
* Deep copy.
*/
AvlTree & operator=( const AvlTree & rhs )
{
AvlTree copy = rhs;
std::swap( *this, copy );
return *this;
}
/**
* Move.
*/
AvlTree & operator=( AvlTree && rhs )
{
std::swap( root, rhs.root );
return *this;
}
/**
* Find the smallest item in the tree.
* Throw UnderflowException if empty.
*/
const Comparable & findMin( ) const
{
if( isEmpty( ) )
throw UnderflowException{ };
return findMin( root )->element;
}
/**
* Find the largest item in the tree.
* Throw UnderflowException if empty.
*/
const Comparable & findMax( ) const
{
if( isEmpty( ) )
throw UnderflowException{ };
return findMax( root )->element;
}
/**
* Returns true if x is found in the tree.
*/
bool contains( const Comparable & x ) const
{
return contains( x, root );
}
/**
* Test if the tree is logically empty.
* Return true if empty, false otherwise.
*/
bool isEmpty( ) const
{
return root == nullptr;
}
/**
* Print the tree contents in sorted order.
*/
void printTree( ) const
{
if( isEmpty( ) )
cout << "Empty tree" << endl;
else
printTree( root );
}
/**
* Make the tree logically empty.
*/
void makeEmpty( )
{
makeEmpty( root );
}
/**
* Insert x into the tree; duplicates are ignored.
*/
void insert( const Comparable & x )
{
insert( x, root );
}
/**
* Insert x into the tree; duplicates are ignored.
*/
void insert( Comparable && x )
{
insert( std::move( x ), root );
}
/**
* Remove x from the tree. Nothing is done if x is not found.
*/
void remove( const Comparable & x )
{
remove( x, root );
}
private:
struct AvlNode
{
Comparable element;
AvlNode *left;
AvlNode *right;
int height;
AvlNode( const Comparable & ele, AvlNode *lt, AvlNode *rt, int h = 0 )
: element{ ele }, left{ lt }, right{ rt }, height{ h } { }
AvlNode( Comparable && ele, AvlNode *lt, AvlNode *rt, int h = 0 )
: element{ std::move( ele ) }, left{ lt }, right{ rt }, height{ h } { }
};
AvlNode *root;
/**
* Internal method to insert into a subtree.
* x is the item to insert.
* t is the node that roots the subtree.
* Set the new root of the subtree.
*/
void insert( const Comparable & x, AvlNode * & t )
{
if( t == nullptr )
t = new AvlNode{ x, nullptr, nullptr };
else if( x < t->element )
insert( x, t->left );
else if( t->element < x )
insert( x, t->right );
balance( t );
}
/**
* Internal method to insert into a subtree.
* x is the item to insert.
* t is the node that roots the subtree.
* Set the new root of the subtree.
*/
void insert( Comparable && x, AvlNode * & t )
{
if( t == nullptr )
t = new AvlNode{ std::move( x ), nullptr, nullptr };
else if( x < t->element )
insert( std::move( x ), t->left );
else if( t->element < x )
insert( std::move( x ), t->right );
balance( t );
}
/**
* Internal method to remove from a subtree.
* x is the item to remove.
* t is the node that roots the subtree.
* Set the new root of the subtree.
*/
void remove( const Comparable & x, AvlNode * & t )
{
if( t == nullptr )
return; // Item not found; do nothing
if( x < t->element )
remove( x, t->left );
else if( t->element < x )
remove( x, t->right );
else if( t->left != nullptr && t->right != nullptr ) // Two children
{
t->element = findMin( t->right )->element;
remove( t->element, t->right );
}
else
{
AvlNode *oldNode = t;
t = ( t->left != nullptr ) ? t->left : t->right;
delete oldNode;
}
balance( t );
}
static const int ALLOWED_IMBALANCE = 1;
// Assume t is balanced or within one of being balanced
void balance( AvlNode * & t )
{
if( t == nullptr )
return;
if( height( t->left ) - height( t->right ) > ALLOWED_IMBALANCE )
if( height( t->left->left ) >= height( t->left->right ) )
rotateWithLeftChild( t );
else
doubleWithLeftChild( t );
else
if( height( t->right ) - height( t->left ) > ALLOWED_IMBALANCE )
if( height( t->right->right ) >= height( t->right->left ) )
rotateWithRightChild( t );
else
doubleWithRightChild( t );
t->height = max( height( t->left ), height( t->right ) ) + 1;
}
/**
* Internal method to find the smallest item in a subtree t.
* Return node containing the smallest item.
*/
AvlNode * findMin( AvlNode *t ) const
{
if( t == nullptr )
return nullptr;
if( t->left == nullptr )
return t;
return findMin( t->left );
}
/**
* Internal method to find the largest item in a subtree t.
* Return node containing the largest item.
*/
AvlNode * findMax( AvlNode *t ) const
{
if( t != nullptr )
while( t->right != nullptr )
t = t->right;
return t;
}
/**
* Internal method to test if an item is in a subtree.
* x is item to search for.
* t is the node that roots the tree.
*/
bool contains( const Comparable & x, AvlNode *t ) const
{
if( t == nullptr )
return false;
else if( x < t->element )
return contains( x, t->left );
else if( t->element < x )
return contains( x, t->right );
else
return true; // Match
}
/****** NONRECURSIVE VERSION*************************
bool contains( const Comparable & x, AvlNode *t ) const
{
while( t != nullptr )
if( x < t->element )
t = t->left;
else if( t->element < x )
t = t->right;
else
return true; // Match
return false; // No match
}
*****************************************************/
/**
* Internal method to make subtree empty.
*/
void makeEmpty( AvlNode * & t )
{
if( t != nullptr )
{
makeEmpty( t->left );
makeEmpty( t->right );
delete t;
}
t = nullptr;
}
/**
* Internal method to print a subtree rooted at t in sorted order.
*/
void printTree( AvlNode *t ) const
{
if( t != nullptr )
{
printTree( t->left );
cout << t->element << endl;
printTree( t->right );
}
}
/**
* Internal method to clone subtree.
*/
AvlNode * clone( AvlNode *t ) const
{
if( t == nullptr )
return nullptr;
else
return new AvlNode{ t->element, clone( t->left ), clone( t->right ), t->height };
}
// Avl manipulations
/**
* Return the height of node t or -1 if nullptr.
*/
int height( AvlNode *t ) const
{
return t == nullptr ? -1 : t->height;
}
int max( int lhs, int rhs ) const
{
return lhs > rhs ? lhs : rhs;
}
/**
* Rotate binary tree node with left child.
* For AVL trees, this is a single rotation for case 1.
* Update heights, then set new root.
*/
void rotateWithLeftChild( AvlNode * & k2 )
{
AvlNode *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
}
/**
* Rotate binary tree node with right child.
* For AVL trees, this is a single rotation for case 4.
* Update heights, then set new root.
*/
void rotateWithRightChild( AvlNode * & k1 )
{
AvlNode *k2 = k1->right;
k1->right = k2->left;
k2->left = k1;
k1->height = max( height( k1->left ), height( k1->right ) ) + 1;
k2->height = max( height( k2->right ), k1->height ) + 1;
k1 = k2;
}
/**
* Double rotate binary tree node: first left child.
* with its right child; then node k3 with new left child.
* For AVL trees, this is a double rotation for case 2.
* Update heights, then set new root.
*/
void doubleWithLeftChild( AvlNode * & k3 )
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 );
}
/**
* Double rotate binary tree node: first right child.
* with its left child; then node k1 with new right child.
* For AVL trees, this is a double rotation for case 3.
* Update heights, then set new root.
*/
void doubleWithRightChild( AvlNode * & k1 )
{
rotateWithLeftChild( k1->right );
rotateWithRightChild( k1 );
}
};
#endif
网友评论