AVL树_插入与删除
来源:互联网 发布:java super重载 编辑:程序博客网 时间:2024/05/17 23:55
以前AVL树学习的很不扎实,昨天复习了一下。代码参考了 http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html
正题二——删除节点是AVL树最繁琐的操作,直接代码中分析之:
打完收工。
哦,其实我基本上代码就是照搬人家的>_<,只不过偷个懒,树的节点里面的数据没用泛型而是直接用char, 然后就是改了几个原文中的小错误。
AVL树节点的定义:
class AVLNode{public:char ch;int height;int freq;AVLNode *left;AVLNode *right;AVLNode(char c = 'a'):ch(c), height(0), freq(0), left(NULL), right(NULL){}void insertNode(AVLNode * &root, AVLNode *node);void deleteNode(AVLNode * &root, AVLNode *node);void search(AVLNode * root, AVLNode *node);int getHeight(AVLNode * root);void singleRotateLeft(AVLNode * &root);void singleRotateRight(AVLNode * &root);void doubleRotateLR(AVLNode * &root);void doubleRotateRL(AVLNode * &root);void traversing_inorder_recursive(AVLNode * root);void printNode(AVLNode * root);};
节点设计,我各种偷懒。access section只有一个public,然后成员函数里面居然还有一个 AVLNode * &类型,而没有直接用this。
主要想集中精力研究AVL树的操作,这里各种违反OOP的设计敬请无视之。
因为每次对树进行修改,都要获取节点的高度,先上getHeight:
int AVLNode::getHeight(AVLNode *root){if(root != NULL)return root->height;elsereturn -1;}
接下来,每次调整树的结构都要用到4种旋转。其中zig-zig型的有左单旋、右单旋;zig-zag型的有双左右旋、双右左旋。
左单旋singleRotateLeft:
void AVLNode::singleRotateLeft(AVLNode * &root)//root相当于图中k2{AVLNode * k1;k1 = root->left;root->left = k1->right;k1->right = root;root->height = max(getHeight(root->left), getHeight(root->right)) + 1;k1->height = max(getHeight(k1->left), root->height) + 1;root = k1;}
对称地,有右单旋singleRotateRight,图略:
void AVLNode::singleRotateRight(AVLNode * &root){AVLNode * k1;k1 = root->right;root->right = k1->left;k1->left = root;root->height = max(getHeight(root->left), getHeight(root->right)) + 1;k1->height = max(root->height, getHeight(k1->right)) + 1;root = k1;}
双左右旋doubleRotateLR:
void AVLNode::doubleRotateLR(AVLNode * &root)//此处root相当于k3{singleRotateRight(root->left);singleRotateLeft(root);}
void AVLNode::doubleRotateRL(AVLNode * &root){singleRotateLeft(root->right);singleRotateRight(root);}
至此旋转终于说完了,可以进入正题——插入节点了= =。
void AVLNode::insertNode(AVLNode * &root, AVLNode *node){if(root == NULL){root = node;return;}if(node->ch < root->ch) //要插入节点的值小于当前root,递归地向root的左子树插入{insertNode(root->left, node);if(getHeight(root->left) - getHeight(root->right) == 2){if(node->ch < root->left->ch)singleRotateLeft(root);elsedoubleRotateLR(root);}}else if(node->ch > root->ch)//要插入节点的值大于当前root,递归地向root的右子树插入{insertNode(root->right, node);if(getHeight(root->right) - getHeight(root->left) == 2){if(node->ch < root->right->ch)doubleRotateRL(root);elsesingleRotateRight(root);}}else//如果相等,当前root节点的频率加一{root->freq++;}root->height = max(getHeight(root->left), getHeight(root->right)) + 1;}
正题二——删除节点是AVL树最繁琐的操作,直接代码中分析之:
void AVLNode::deleteNode(AVLNode * &root, AVLNode *node){if(root == NULL)return;if(node->ch < root->ch)//递归地从左子树删除此节点{deleteNode(root->left, node);if(getHeight(root->right) - getHeight(root->left) == 2){if(root->right->left != NULL && getHeight(root->right->left) > getHeight(root->right->right) ){doubleRotateRL(root);}else{singleRotateRight(root);}}}else if(node->ch > root->ch)//递归地从右子树删除此节点{deleteNode(root->right, node);if(getHeight(root->left) - getHeight(root->right) == 2){if(root->left->right != NULL && getHeight(root->left->right) > getHeight(root->left->left)){doubleRotateLR(root);}else{singleRotateLeft(root);}}}else//当前节点就是要删除的节点{if(root->left && root->right)//有左右两个儿子{/*找右子树的最左节点,即大于根节点的最小节点*/AVLNode *tmp = root->right;while(tmp->left != NULL)tmp = tmp->left;/*把右子树的最左节点的值赋给根节点*/root->ch = tmp->ch;root->freq = tmp->freq;/*递归地删除右子树的最左节点*/deleteNode(root->right, tmp);if(getHeight(root->left) - getHeight(root->right) == 2){if(root->left->right != NULL && getHeight(root->left->right) > getHeight(root->left->left)){doubleRotateLR(root);}else{singleRotateLeft(root);}}}else{AVLNode * tmp = root;if(!root->left && root->right)//只有右儿子{root = root->right;}else if(root->left && !root->right)//只有左儿子{root = root->left;}else//没有儿子{root = NULL;}/*如果构成树的节点都是堆变量,那需要delete指针并将指针置为NULL。我的测试用例中,树的节点均用栈变量,故不需要。*///delete(tmp);//tmp = NULL;}}if(root == NULL)return;root->height = max(getHeight(root->left), getHeight(root->right)) + 1;return;}
- AVL树_插入与删除
- AVL树的插入与删除
- avl树的插入与删除
- AVL树的插入与删除
- AVL树的插入与删除操作
- AVL树的插入与删除
- AVL树的插入与删除
- AVL树的插入与删除
- AVL树的插入与删除
- AVL树插入删除
- (转)AVL树的插入_删除操作
- AVL树的插入_删除操作实现~
- AVL树实现(插入删除)
- AVL树插入、删除的分析与实现
- AVL树的插入与删除---Java实现
- AVL树的插入与删除,重点是四种旋转
- AVL树的插入与删除(均为递归实现)
- AVL树的插入删除分析
- 由String s=new String ("abc");引发的联想(类对象引用)
- JAVA运行【本地程序】
- httpRuntime 元素(ASP.NET 设置架构)
- 1057 字符变换
- servlet工作原理
- AVL树_插入与删除
- 修改系统tabbar的高度
- 用户管理
- 【AngularJS】 1. Angular JS的五大特性
- 分享几道黑马程序员训练营.NET基础测试题
- 《Pro Git》学习笔记
- 【jiasuba】不为人知的Word手动更新链接设置
- Delphi 三层 实例(1)
- MySQL Linux压缩版安装方法