AVL树的基本操作 C++

来源:互联网 发布:苹果数据接口转usb 编辑:程序博客网 时间:2024/05/16 10:04
#ifndef _AVLTREE_#define _AVLTREE_#include<algorithm>/*AVL树:1.它必须是二叉查找树。2.每个节点的左子树和右子树的高度差至多为1AVL树的查找、插入、删除操作在平均和最坏的情况下都是O(logn)平衡因子:将二叉树上节点的左子树高度减去右子树高度的值称为该节点的平衡因子,BF的取值范围为[-1,1]最小不平衡子树:距离插入节点最近的,且平衡因子的绝对值大于1的节点为根的子树。*/struct AVLTreeNode{AVLTreeNode(int value, AVLTreeNode* l, AVLTreeNode* r) :key(value), lchild(l), rchild(r){};int key;int height;AVLTreeNode* lchild;AVLTreeNode* rchild;};class AVLTree{public:AVLTree();            //构造函数~AVLTree();            //析构函数void preOrder();    //前序遍历AVL树void inOrder();        //中序遍历AVL树   void postOrder();    //后序遍历AVL树void print();        //打印AVL树void destory();        //销毁AVL树void insert(int key);    //插入指定值的节点void remove(int key);    //移除指定值的节点AVLTreeNode* search_recurse(int key);    //利用递归算法进行指定值的查找AVLTreeNode* search_iterator(int key);    //利用迭代算法进行指定值的查找int minimum();        //返回AVL中的最小值int maximum();        //返回AVL中的最大值int height();        //返回树的高度private:AVLTreeNode* root;    //AVL树的根节点private:void preOrder(AVLTreeNode* pnode) const;void inOrder(AVLTreeNode* pnode) const;void postOrder(AVLTreeNode* pnode) const;void print(AVLTreeNode* pnode, int key, int direction) const;void destory(AVLTreeNode* & pnode);AVLTreeNode* insert(AVLTreeNode* &pnode, int key);AVLTreeNode* remove(AVLTreeNode* & pnode, int key); //删除AVL树中节点pdel,并返回被删除的节点AVLTreeNode* minimum(AVLTreeNode*pnode)const;AVLTreeNode* maximum(AVLTreeNode*pnode)const;int height(AVLTreeNode* pnode);AVLTreeNode* search_recurse(AVLTreeNode* pnode, int key) const;AVLTreeNode* search_iterator(AVLTreeNode* pnode, int key) const;AVLTreeNode* leftRotation(AVLTreeNode* pnode);        //单旋:左旋操作AVLTreeNode* rightRotation(AVLTreeNode* pnode);        //单旋:右旋操作AVLTreeNode* leftRightRotation(AVLTreeNode* pnode);    //双旋:先左旋后右旋操作AVLTreeNode* rightLeftRotation(AVLTreeNode* pnode);    //双旋:先右旋后左旋操作};int AVLTree::height(){return height(root);}int AVLTree::height(AVLTreeNode* pnode){if (pnode != nullptr)return pnode->height;elsereturn -1;}/*AVL树失衡调整:(节点的插入或删除都有可能导致AVL树失去平衡)单左旋:旋转围绕最小失衡子树的根节点进行。在左子树插入左孩子节点*/AVLTreeNode* AVLTree::leftRotation(AVLTreeNode* pnode){AVLTreeNode* prchild = pnode->rchild;if (prchild->lchild != nullptr)pnode->rchild = prchild->lchild;prchild->lchild = pnode;//更新节点高低pnode->height = std::max(height(pnode->lchild), height(pnode->rchild)) + 1;prchild->height = std::max(height(prchild->lchild), height(prchild->rchild)) + 1;}/*右单旋转在右子树插入右孩子节点*/AVLTreeNode* AVLTree::rightRotation(AVLTreeNode* pnode){AVLTreeNode* plchild = pnode->lchild;if (plchild->rchild != nullptr)pnode->lchild = plchild->rchild;plchild->lchild = pnode;pnode->height = std::max(height(pnode->lchild), height(pnode->rchild)) + 1;plchild->height = std::max(height(plchild->lchild), height(plchild->rchild)) + 1;}/*先右旋后左旋:在右子树上插入左孩子导致AVL树失衡*/AVLTreeNode* AVLTree::rightLeftRotation(AVLTreeNode* pnode){pnode->rchild = rightRotation(pnode->rchild);return leftRotation(pnode);}/*先左旋后右旋:在左子树上插入右孩子导致AVL树失衡*/AVLTreeNode* AVLTree::leftRightRotation(AVLTreeNode* pnode){pnode->lchild = leftRotation(pnode->lchild);return rightRotation(pnode);}/*插入新节点*/AVLTreeNode* AVLTree::insert(AVLTreeNode* &pnode, int key){if (pnode == nullptr)pnode = new AVLTreeNode(key, nullptr, nullptr);else if(key>pnode->key){pnode->rchild = insert(pnode->rchild, key);if (height(pnode->rchild) - height(pnode->lchild) == 2)//插入后失衡{if (key > pnode->rchild->key)pnode = leftRotation(pnode);else if (key < pnode->rchild->key)pnode = rightLeftRotation(pnode);}}else if (key < pnode->key){pnode->lchild = insert(pnode->lchild, key);if (height(pnode->lchild) - height(pnode->rchild) == 2)//插入后失衡{if (key > pnode->lchild->key)pnode = rightRotation(pnode);else if (key < pnode->lchild->key)pnode = leftRightRotation(pnode);}}pnode->height = std::max(height(pnode->lchild), height(pnode->rchild)) + 1;return pnode;}/*删除节点:删除节点也可能导致AVL树的失衡,实际上删除节点和插入节点是一种互逆的操作删除右子树的节点导致AVL树失衡时,相当于在左子树插入节点导致AVL树失衡,即情况情况二或情况四。删除左子树的节点导致AVL树失衡时,相当于在右子树插入节点导致AVL树失衡,即情况情况一或情况三。另外,AVL树也是一棵二叉排序树,因此在删除节点时也要维护二叉排序树的性质删除节点时,如果节点同时拥有左子树和右子树,则在高度教低的子树上选择最大(或最小)元素进行替换,这样能保证替换后不会再出现失衡的现象。*/AVLTreeNode* AVLTree::remove(AVLTreeNode* & pnode, int key){if (pnode != nullptr){if (key == pnode->key)//找到删除节点{//因为AVL也是二叉排序树,删除节点要维护其二叉排序树的条件if (pnode->lchild != nullptr && pnode->rchild != nullptr){//左子树比右子树高,在左子树上选择节点进行替换if (height(pnode->lchild) > height(pnode->rchild)){AVLTreeNode* ppre = maximum(pnode->lchild);pnode->key = ppre->key;pnode->lchild = remove(pnode->lchild, ppre->key);}else{//在右子树上选择节点进行替换AVLTreeNode* ppre = maximum(pnode->rchild);pnode->key = ppre->key;pnode->rchild = remove(pnode->rchild, ppre->key);}}else{AVLTreeNode* ptmp = pnode;if (pnode->lchild != nullptr)pnode = pnode->lchild;else if (pnode->rchild != nullptr)pnode = pnode->rchild;delete ptmp;return nullptr;}}else if (key > pnode->key)//要删除的节点比当前点大,则在右子树进行删除{pnode->rchild = remove(pnode->rchild, key);//删除了右节点,可能失衡if (height(pnode->lchild) - height(pnode->rchild) == 2){//相当于在左子树上插入右节点造成失衡if (height(pnode->lchild->rchild) > height(pnode->lchild->lchild))pnode = leftRightRotation(pnode);elsepnode = rightRotation(pnode);}}else if (key < pnode->key){pnode->lchild = remove(pnode->lchild, key);if (height(pnode->rchild) - height(pnode->lchild) == 2){//相当于在右子树上插入左节点造成的失衡if (height(pnode->rchild->lchild) - height(pnode->rchild->rchild))pnode = rightLeftRotation(pnode);else//相当于在右子树上插入右节点造成的失衡pnode = leftRotation(pnode);}}return pnode;}return nullptr;}/*查找元素*///递归查找AVLTreeNode* AVLTree::search_recurse(int key){return search_recurse(root, key);}AVLTreeNode* AVLTree::search_recurse(AVLTreeNode* pnode, int key){if (pnode != nullptr){if (key == pnode->key)return pnode;else if (key > pnode->key)return search_recurse(pnode->rchild, key);elsereturn search_recurse(pnode->lchild, key);}return nullptr;}//迭代查找AVLTreeNode* AVLTree::search_iterator(int key){return search_iterator(root, key);}AVLTreeNode* AVLTree::search_iterator(AVLTreeNode* pnode, int key){if (pnode != nullptr){if (pnode->key == key)return pnode;else if (key > pnode->key)pnode = pnode->rchild;else pnode = pnode->lchild;}return nullptr;}/*遍历二叉树*///前序:根左右void AVLTree::preOrder(){return preOrder(root);}void AVLTree::preOrder(AVLTreeNode* pnode){if (pnode!=nullptr){cout << pnode->key;preOrder(pnode->lchild);preOrder(pnode->rchild);}}//中序:左根右void AVLTree::inOrder(){return inOrder(root);}void AVLTree::inOrder(AVLTreeNode* pnode){if (pnode != nullptr){inOrder(pnode->lchild);cout << pnode->key;inOrder(pnode->rchild);}}//后序:左右根void AVLTree::postOrder(){return postOrder(root);}void AVLTree::postOrder(AVLTreeNode* pnode){if (pnode != nullptr){postOrder(pnode->lchild);postOrder(pnode->rchild);cout << pnode->key;}}//销毁:只有后序void AVLTree::destory(){return destory(root);}void AVLTree::destory(AVLTreeNode* & pnode){if (pnode != nullptr){destory(pnode->lchild);destory(pnode->rchild);delete pnode;pnode = nullptr;}}/*求最大最小值:二叉排序树的最小值位于最左节点,最大值位于其最右节点。*/AVLTreeNode* AVLTree::maximum(AVLTreeNode* pnode) const{while (pnode!= nullptr){while (pnode->rchild != nullptr)pnode = pnode->rchild;return pnode;}return nullptr;}int AVLTree::maximum(){AVLTreeNode* presult = maximum(root);if (presult != nullptr)return presult->key;}AVLTreeNode* AVLTree::minimum(AVLTreeNode*pnode){while (pnode != nullptr){while (pnode->lchild != nullptr)pnode = pnode->lchild;return pnode;}return nullptr;}int AVLTree::minimum(){AVLTreeNode* presult = minimum(root);if (presult != nullptr)return presult->key;}#endif

原创粉丝点击