AVLTree本身就是二叉查找树。为了保证查找效率在O(nlogn),所以有时要对树高进行必要的调整。
AVLTree拥有自己的法则使得插入、删除、查找都在O(nlogn)时间内完成。
下面写了一个AVLTreeNode类,好像和TreeNode类一样。
下面写AVLTree类,这个类重要的地方在与插入和删除操作。查找操作和BinarySearchTree一致。但是至今还没有找到一个有效的方法来使用BinarySearchTree中的Search。除非将Search方法抽象为一个接口。
暂时先不管太多。
先看左旋和右旋操作。
这里旋转后调整平衡因子是关键部分。这是我自己总结的方法,经少量测试暂时没有出现问题。这个调整方法好像与大多数书本和网络程序的方法不一致。不清楚到底哪个是正确的。但是如果不使用这种直接赋值的方法,可以使用递归查找树高的方法保障万无一失的解决这个问题。这里使用的右树高减左树高得平衡因子的方法。
下面给出这样的两个函数,其中getAVLHeight是核心方法。
- int getHeight(AVLNode<T>* node)
- {
- if(node == NULL)
- {
- return 0;
- }
- else
- {
- int leftHeight = getHeight(node->getLeft());
- int rightHeight = getHeight(node->getRight());
- if(leftHeight > rightHeight)
- {
- return leftHeight+1;
- }
- else
- {
- return rightHeight+1;
- }
- }
- }
- int getAVLHeight(AVLNode<T>* node)
- {
- if(node == NULL)
- {
- return 0;
- }
- else
- {
- int leftHeight = getHeight(node->getLeft());
- int rightHeight = getHeight(node->getRight());
- return rightHeight - leftHeight;
- }
- }
删除、插入操作有点复杂。
插入操作:
1.先找到可能要调整的那个节点A,这里的可能要调整的节点即为插入路径中平衡因子为+1或者为-1的点。(这里一定要记得不要自作聪明的认为如果向左插入,+1节点就不会是可能节点)
2.插入应该插入的节点,调整从A至目标节点的平衡因子。并且记录是否增长了子树树高(是否插入节点没有兄弟节点)。
3.插入后查看是否增长子树树高,如果增长树高,再查看A是否已经不平衡。如果不平衡,调整,否则,插入完成。
(这里要注意A节点为树根的情况,或者无A节点的情况)
因为下面的程序首先将树根设定为可能要调整的节点A,所以没有出现无A节点的情况。
以上三点,我看过很多教科书,发现讲解有些含糊,或者本身就是略写。这里并没有采用递归操作。
再看删除操作。
采用的是http://www.cs.uga.edu/~eileen/2720/Notes/AVLTrees-II.ppt这个ppt介绍的删除操作。
因为删除操作要反遍历到树根,所以这里无奈采用是递归操作。
bool deleteNode(AVLNode<T>* subRoot, AVLNode<T>* prev, T& node);
这个操作返回值:如果子树树高变化,那么返回true,否则返回false。
1.如果子树为Null,函数返回false
2.比较subRoot里的data值和node中的data值。
A.如果subRoot->data< node.data,需要递归下右子树,如果这个递归返回true,将subRoot的平衡因子调整为-1,如果为false就return false。
B.subRoot->data > node.data需要递归下左子树,如果这个递归返回true,将subRoot的平衡因子调整为+1,如果为false就return false。
C.subRoot->data == node.data.
1)如果此时subRoot只有一个孩子或者没有孩子,那么删除时树高一定会改变。另外做一个简单的删除操作即可。该左孩子代替此节点还是右孩子代替它,如何代替其实和BinarySearchTree一样。再return true
2)如果有两个孩子,去左子树中找到替代品,然后将这个subRoot的数据域完全变为此替代品后,去左子树中用再用deleteNode方法将替代品删除。如果deleteNode操作返回true,那么显然subRoot的平衡因子要加1.
3.如果subRoot的平衡因子已经为2或者-2,那么以subRoot为根开始调整。
A.如果调整后subRoot平衡因子为0,return true
B.不为0,return false。
下面是实际代码
- bool deleteNode(AVLNode<T>* subRoot, AVLNode<T>* prev, T& node)
- {
- if(subRoot == NULL)
- {
- return false;
- }
- bool isChangeHeight = false;
- if(subRoot->getData() > node)
- {
- isChangeHeight = deleteNode(subRoot->getLeft(),subRoot,node);
- if(isChangeHeight)
- {
- subRoot->setAHeight(subRoot->getAHeight()+1);
- }
-
- }
- else if(subRoot->getData() < node)
- {
- isChangeHeight = deleteNode(subRoot->getRight(),subRoot,node);
- if(isChangeHeight)
- {
- subRoot->setAHeight(subRoot->getAHeight()-1);
- }
-
- }
- else
- {
- AVLNode<T>* assignNode = NULL;
- if(subRoot->getLeft() == NULL && subRoot->getRight() == NULL)
- {
-
- isChangeHeight = true;
- deleteNode(subRoot,prev,assignNode);
- return isChangeHeight;
- }
- else if(subRoot->getLeft() == NULL && subRoot->getRight() != NULL)
- {
-
- isChangeHeight = true;
- assignNode = subRoot->getRight();
- deleteNode(subRoot,prev,assignNode);
- return isChangeHeight;
-
- }
- else if(subRoot->getRight() == NULL && subRoot->getLeft() != NULL)
- {
-
- isChangeHeight = true;
- assignNode = subRoot->getLeft();
- deleteNode(subRoot,prev,assignNode);
- return isChangeHeight;
- }
- else
- {
-
- assignNode = getMaxNode(subRoot->getLeft());
- T data = assignNode->getData();
- bool isChange = deleteNode(subRoot->getLeft(),subRoot,data);
- cout << "use "<< data<< " replace "<< subRoot->getData()<<endl;
- subRoot->setData(data);
-
- if(isChange)
- {
- subRoot->setAHeight(subRoot->getAHeight()+1);
- }
- }
- if(subRoot->getAbsoluteAHeight() == 2)
- {
- AVLNode<T>* a = subRoot;
- AVLNode<T>* b = NULL;
- AVLNode<T>* c = NULL;
- AVLNode<T>* tempRoot = NULL;
- if(subRoot->getAHeight() == 2)
- {
-
- b = subRoot->getRight();
- switch(b->getAHeight())
- {
- case 1:
- tempRoot = RRRotate(a,b);
- isChangeHeight = true;
- break;
- case -1:
- c = b->getLeft();
- tempRoot = RLRotate(a,b,c);
- isChangeHeight = true;
- break;
- case 0:
- tempRoot = RRRotate(a,b);
- isChangeHeight = false;
- break;
- }
- }
- else if(subRoot->getAHeight() == -2)
- {
-
- b = subRoot->getLeft();
- switch(b->getAHeight())
- {
- case 1:
- c = b->getRight();
- tempRoot = LRRotate(a,b,c);
- isChangeHeight = true;
- break;
- case -1:
- tempRoot = LLRotate(a,b);
- isChangeHeight = true;
- break;
- case 0:
- tempRoot = LLRotate(a,b);
- isChangeHeight = false;
- break;
- }
- }
- if(prev == NULL)
- {
- this->head = tempRoot;
- }
- else
- {
- if(prev->getData() > tempRoot->getData())
- {
- prev->setLeft(tempRoot);
- }
- else
- {
- prev->setRight(tempRoot);
- }
- }
- }
- }
- return isChangeHeight;
- }
最后贴上AVLTree的完整类代码
- #include "AVLNode.h"
- template<class T>
- class AVLTree
- {
- private:
- AVLNode<T>* head;
- int getHeight(AVLNode<T>* node)
- {
- if(node == NULL)
- {
- return 0;
- }
- else
- {
- int leftHeight = getHeight(node->getLeft());
- int rightHeight = getHeight(node->getRight());
- if(leftHeight > rightHeight)
- {
- return leftHeight+1;
- }
- else
- {
- return rightHeight+1;
- }
- }
- }
- int getAVLHeight(AVLNode<T>* node)
- {
- if(node == NULL)
- {
- return 0;
- }
- else
- {
- int leftHeight = getHeight(node->getLeft());
- int rightHeight = getHeight(node->getRight());
- return rightHeight - leftHeight;
- }
- }
- void clearSubTree(AVLNode<T>* node)
- {
- if(node != NULL)
- {
- clearSubTree(node->getLeft());
- clearSubTree(node->getRight());
- delete node;
- }
- }
- void printTree(AVLNode<T>* subTree, int count)
- {
- if(subTree!=NULL)
- {
-
- printTree(subTree->getRight(), count+1);
- for(int i = 0; i < count; i++)
- {
- cout << " ";
- }
- cout <<subTree->getData()<<endl;
- printTree(subTree->getLeft(),count+1);
- }
- }
- void printInMidOrder(AVLNode<T>* subTree)
- {
- if(subTree!=NULL)
- {
- printInMidOrder(subTree->getLeft());
-
- cout <<subTree->getData()<<endl;
- printInMidOrder(subTree->getRight());
- }
- }
- bool isPossibleNode(AVLNode<T>* node, AVLNode<T>* comNode)
- {
- if(node != NULL && node->getAbsoluteAHeight() == 1)
- {
- return true;
- }
- return false;
- }
- void insertNode(AVLNode<T>* node)
- {
- AVLNode<T>* subRoot = this->head;
- if(subRoot == NULL)
- {
- subRoot = node;
- return;
- }
- AVLNode<T>* ppoRoot = NULL;
- AVLNode<T>* poRoot = NULL;
- AVLNode<T>* pRoot = NULL;
-
-
- poRoot = subRoot;
-
- while(subRoot != NULL)
- {
- pRoot = subRoot;
- if(subRoot->getData() > node->getData())
- {
-
- if(isPossibleNode(subRoot->getLeft(),node))
- {
- poRoot = subRoot->getLeft();
- ppoRoot = subRoot;
- }
- subRoot = subRoot->getLeft();
- }
- else if(subRoot->getData() < node->getData())
- {
-
- if(isPossibleNode(subRoot->getRight(),node))
- {
- poRoot = subRoot->getRight();
- ppoRoot = subRoot;
- }
- subRoot = subRoot->getRight();
- }
- else
- {
- throw "the same key";
- }
- }
- bool isChangeHeight = false;
- if(pRoot->getData() > node->getData())
- {
-
- pRoot->setLeft(node);
- if(pRoot->getRight() == NULL)
- {
- isChangeHeight = true;
- }
- else
- {
- pRoot->setAHeight(pRoot->getAHeight()-1);
- }
- }
- else if(pRoot->getData() < node->getData())
- {
-
- pRoot->setRight(node);
- if(pRoot->getLeft() == NULL)
- {
- isChangeHeight = true;
- }
- else
- {
- pRoot->setAHeight(pRoot->getAHeight()+1);
- }
- }
- if(poRoot != NULL && isChangeHeight)
- {
-
- subRoot = poRoot;
- while(subRoot != node)
- {
- if(subRoot->getData() > node->getData())
- {
- subRoot->setAHeight(subRoot->getAHeight()-1);
-
- subRoot = subRoot->getLeft();
- }
- else if(subRoot->getData() < node->getData())
- {
- subRoot->setAHeight(subRoot->getAHeight()+1);
-
- subRoot = subRoot->getRight();
- }
- }
- subRoot = poRoot;
- AVLNode<T>* a = poRoot;
- AVLNode<T>* b = NULL;
- AVLNode<T>* c = NULL;
- AVLNode<T>* tempRoot = NULL;
- if(a->getAbsoluteAHeight() > 1)
- {
- if(subRoot->getData() > node->getData())
- {
- b = subRoot->getLeft();
- if(a->getAHeight()* b->getAHeight() > 0)
- {
-
- tempRoot = LLRotate(a,b);
-
- }
- else
- {
-
- c = b->getRight();
- tempRoot =LRRotate(a,b,c);
- }
-
- }
- else if(subRoot->getData() < node->getData())
- {
- b = subRoot->getRight();
- if(a->getAHeight()* b->getAHeight() > 0)
- {
-
- tempRoot = RRRotate(a,b);
- }
- else
- {
-
- c = b->getLeft();
- tempRoot =RLRotate(a,b,c);
- }
- }
- if(ppoRoot!=NULL)
- {
- if(ppoRoot->getData() > tempRoot->getData())
- {
- ppoRoot->setLeft(tempRoot);
- }
- else
- {
- ppoRoot->setRight(tempRoot);
- }
- }
- else
- {
- this->head = tempRoot;
- }
- }
-
- }
- }
-
-
-
-
-
-
- AVLNode<T>* LLRotate(AVLNode<T>* a, AVLNode<T>* b)
- {
- a->setLeft(b->getRight());
- b->setRight(a);
-
- a->setAHeight(0);
- b->setAHeight(0);
-
-
- return b;
- }
-
-
-
-
-
-
- AVLNode<T>* RRRotate(AVLNode<T>* a, AVLNode<T>* b)
- {
- a->setRight(b->getLeft());
- b->setLeft(a);
-
- a->setAHeight(0);
- b->setAHeight(0);
-
-
- return b;
- }
-
-
-
-
-
-
-
-
- AVLNode<T>* RLRotate(AVLNode<T>* a, AVLNode<T>* b, AVLNode<T>* c)
- {
-
- b->setLeft(c->getRight());
- c->setRight(b);
- a->setRight(c->getLeft());
- c->setLeft(a);
-
-
-
-
-
- if(c->getAbsoluteAHeight() == 1)
- {
- if(b->getAHeight() == 0)
- {
- b->setAHeight(-1);
- }
- else
- {
- b->setAHeight(0);
- }
- a->setAHeight(1);
- c->setAHeight(0);
-
- }
- else
- {
- if(b->getAHeight() == 0)
- {
- b->setAHeight(-1);
- }
- else
- {
- b->setAHeight(0);
- }
- a->setAHeight(0);
- c->setAHeight(0);
-
- }
-
-
- return c;
- }
-
-
-
-
-
-
-
-
- AVLNode<T>* LRRotate(AVLNode<T>* a, AVLNode<T>* b, AVLNode<T>* c)
- {
- b->setRight(c->getLeft());
- c->setLeft(b);
- a->setLeft(c->getRight());
- c->setRight(a);
-
-
-
-
-
- if(c->getAbsoluteAHeight() == 1)
- {
- if(b->getAHeight() == 0)
- {
- b->setAHeight(1);
- }
- else
- {
- b->setAHeight(0);
- }
- a->setAHeight(-1);
- c->setAHeight(0);
-
- }
- else
- {
- if(b->getAHeight() == 0)
- {
- b->setAHeight(1);
- }
- else
- {
- b->setAHeight(0);
- }
- a->setAHeight(0);
- c->setAHeight(0);
-
- }
-
-
-
- return c;
- }
- AVLNode<T>* getMaxNode(AVLNode<T>* subRoot)
- {
- if(subRoot == NULL)
- {
- return NULL;
- }
- if(subRoot->getRight() == NULL)
- {
- return subRoot;
- }
- else
- {
- return getMaxNode(subRoot->getRight());
- }
- }
- void deleteNode(AVLNode<T>* subRoot, AVLNode<T>* prev,AVLNode<T>* assignNode)
- {
- if(prev == NULL)
- {
- this->head = assignNode;
- }
- else
- {
- if(prev->getLeft() == subRoot)
- {
- prev->setLeft(assignNode);
-
- }
- else if(prev->getRight() == subRoot)
- {
- prev->setRight(assignNode);
-
- }
- }
-
- delete subRoot;
- }
- bool deleteNode(AVLNode<T>* subRoot, AVLNode<T>* prev, T& node)
- {
- if(subRoot == NULL)
- {
- return false;
- }
- bool isChangeHeight = false;
- if(subRoot->getData() > node)
- {
- isChangeHeight = deleteNode(subRoot->getLeft(),subRoot,node);
- if(isChangeHeight)
- {
- subRoot->setAHeight(subRoot->getAHeight()+1);
- }
-
- }
- else if(subRoot->getData() < node)
- {
- isChangeHeight = deleteNode(subRoot->getRight(),subRoot,node);
- if(isChangeHeight)
- {
- subRoot->setAHeight(subRoot->getAHeight()-1);
- }
-
- }
- else
- {
- AVLNode<T>* assignNode = NULL;
- if(subRoot->getLeft() == NULL && subRoot->getRight() == NULL)
- {
-
- isChangeHeight = true;
- deleteNode(subRoot,prev,assignNode);
- return isChangeHeight;
- }
- else if(subRoot->getLeft() == NULL && subRoot->getRight() != NULL)
- {
-
- isChangeHeight = true;
- assignNode = subRoot->getRight();
- deleteNode(subRoot,prev,assignNode);
- return isChangeHeight;
-
- }
- else if(subRoot->getRight() == NULL && subRoot->getLeft() != NULL)
- {
-
- isChangeHeight = true;
- assignNode = subRoot->getLeft();
- deleteNode(subRoot,prev,assignNode);
- return isChangeHeight;
- }
- else
- {
-
- assignNode = getMaxNode(subRoot->getLeft());
- T data = assignNode->getData();
- bool isChange = deleteNode(subRoot->getLeft(),subRoot,data);
- cout << "use "<< data<< " replace "<< subRoot->getData()<<endl;
- subRoot->setData(data);
-
- if(isChange)
- {
- subRoot->setAHeight(subRoot->getAHeight()+1);
- }
- }
- if(subRoot->getAbsoluteAHeight() == 2)
- {
- AVLNode<T>* a = subRoot;
- AVLNode<T>* b = NULL;
- AVLNode<T>* c = NULL;
- AVLNode<T>* tempRoot = NULL;
- if(subRoot->getAHeight() == 2)
- {
-
- b = subRoot->getRight();
- switch(b->getAHeight())
- {
- case 1:
- tempRoot = RRRotate(a,b);
- isChangeHeight = true;
- break;
- case -1:
- c = b->getLeft();
- tempRoot = RLRotate(a,b,c);
- isChangeHeight = true;
- break;
- case 0:
- tempRoot = RRRotate(a,b);
- isChangeHeight = false;
- break;
- }
- }
- else if(subRoot->getAHeight() == -2)
- {
-
- b = subRoot->getLeft();
- switch(b->getAHeight())
- {
- case 1:
- c = b->getRight();
- tempRoot = LRRotate(a,b,c);
- isChangeHeight = true;
- break;
- case -1:
- tempRoot = LLRotate(a,b);
- isChangeHeight = true;
- break;
- case 0:
- tempRoot = LLRotate(a,b);
- isChangeHeight = false;
- break;
- }
- }
- if(prev == NULL)
- {
- this->head = tempRoot;
- }
- else
- {
- if(prev->getData() > tempRoot->getData())
- {
- prev->setLeft(tempRoot);
- }
- else
- {
- prev->setRight(tempRoot);
- }
- }
- }
- }
- return isChangeHeight;
- }
-
- public:
- AVLTree(T& data)
- {
- head = new AVLNode<T>(data);
- }
- AVLTree(AVLNode<T>* head)
- {
- clearSubTree(this->head);
- this->head = head;
- }
- ~AVLTree()
- {
- clearSubTree(head);
- }
- void printTree()
- {
- printTree(this->head,0);
- }
- void printInMidOrder()
- {
- printInMidOrder(this->head);
- }
- void insertNode(T& data)
- {
- insertNode(new AVLNode<T>(data));
- }
- void deleteNode(T& data)
- {
- deleteNode(this->head,NULL,data);
- }
-
- };