AVL树(平衡二叉树)的构造
2016-10-27 19:27
567 查看
特点:平衡二叉树要求对于每一个节点来说,他的左右子树的高度之差不超过1,如果插入或者删除一个结点使得高度之差大于1,就要进行节点之间的旋转(左旋或者右旋),将二叉树重新维持在一个平衡状态。
解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最坏和最好情况都维持在O(logN)。
旋转缺点:频繁旋转会牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了许多。
平衡二叉树的核心:
旋转算法
1:左左形式的不平衡
2.左右形式的不平衡
3.右左形式的不平衡
4.右右形式的不平衡
1,4一组
2,3一组
对于1:左旋 3的右子树给6的左边,6变成3的右子树,3成根
确定要换的根root和左子树left,left的右子树给root的左,root变成left的右
对于4:右旋 4的左子树给2的右边,2变成4的左子树,2成根
确定要换的根root和右子树right,right的左子树给root的右然后root变成right的左
对于2:先右旋左子树,再左旋根
对于3:先左旋右子书,再右旋根
代码如下:
解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最坏和最好情况都维持在O(logN)。
旋转缺点:频繁旋转会牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了许多。
平衡二叉树的核心:
旋转算法
1:左左形式的不平衡
2.左右形式的不平衡
3.右左形式的不平衡
4.右右形式的不平衡
1,4一组
2,3一组
对于1:左旋 3的右子树给6的左边,6变成3的右子树,3成根
确定要换的根root和左子树left,left的右子树给root的左,root变成left的右
对于4:右旋 4的左子树给2的右边,2变成4的左子树,2成根
确定要换的根root和右子树right,right的左子树给root的右然后root变成right的左
对于2:先右旋左子树,再左旋根
对于3:先左旋右子书,再右旋根
代码如下:
#include <iostream> #include <malloc.h> #include <stack> using namespace std; typedef struct TreeNode { int height; int data; TreeNode* leftC; TreeNode* rightC; }TreeNode; int getHeight(TreeNode* s) { if (s != NULL) { return s->height; } return -1; } void InitTree(TreeNode** list) { *list = (TreeNode*)malloc(sizeof(TreeNode)); (*list)->height = 0; (*list)->leftC = NULL; (*list)->rightC = NULL; } void leftRotate(TreeNode*& root)//左左 { TreeNode *l1 = root; TreeNode *l2 = root->leftC; l1->leftC = l2->rightC; l2->rightC = l1; l1->height = (getHeight(l1->leftC) > getHeight(l1->rightC) ? getHeight(l1->leftC) : getHeight(l1->rightC)) + 1; l2->height = (getHeight(l2->leftC) > getHeight(l2->rightC) ? getHeight(l2->leftC) : getHeight(l2->rightC)) + 1; root = l2; } void rightRotate(TreeNode*& root)//右右 { TreeNode *l1 = root; TreeNode *l2 = root->rightC; l1->rightC = l2->leftC; l2->leftC = l1; l1->height = getHeight(l1); l2->height = getHeight(l2); root = l2; } ///左右,先右旋,再左旋 void DoubleRotateLR(TreeNode* &n1) { rightRotate(n1->leftC); leftRotate(n1); } //右左,先左旋,后右旋 void DoubleRotateRL(TreeNode* &n1) { leftRotate(n1->rightC); rightRotate(n1); } void Insert(TreeNode*& node, int data) { if (node == NULL) { TreeNode* tmp = (TreeNode*)malloc(sizeof(TreeNode)); tmp->data = data; tmp->height = 0; tmp->leftC = NULL; tmp->rightC = NULL; node = tmp; return; } if (node->data > data)//结点的值大于data { Insert(node->leftC, data);//不断插入 if ((getHeight(node->leftC) - getHeight(node->rightC)) == 2) {//说明需要左旋 if (data < node->leftC->data) { leftRotate(node); } else { DoubleRotateLR(node); } } else if (node->data < data)//没有相同的值 { Insert(node->rightC, data); //如果高度之差为2的话就失去了平衡,需要旋转 if (2 == getHeight(node->rightC) - getHeight(node->leftC)) { if (data > node->rightC->data) { rightRotate(node); } else { DoubleRotateRL(node); } } } } node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1; } void preOrder(TreeNode* node) { if (node == NULL) { return; } cout << node->data << endl; preOrder(node->leftC); preOrder(node->rightC); } void inOrderTraversal(TreeNode* root)//非递归中序遍历 {//先左,再中,最后右,对于每个子树也是一样的顺序 stack<TreeNode *> S; while (true) { if (root) { S.push(root); root = root->leftC; } else { if (S.empty()) { break; } root = S.top(); cout << root->data << " "; S.pop(); root = root->rightC; } } } void deleteNode(TreeNode* &node, int x) { if (node == NULL) return; //没有找到值是x的节点 if (x < node->data) { //如果x小于节点的值,就继续在节点的左子树中删除x deleteNode(node->leftC, x); if (2 == getHeight(node->rightC) - getHeight(node->leftC)) { if (node->rightC->leftC && getHeight(node->rightC->leftC) > getHeight(node->rightC->rightC)) DoubleRotateRL(node); else rightRotate(node); } } else if (x > node->data) { //如果x大于节点的值,就继续在节点的右子树中删除x deleteNode(node->rightC, x); if (2 == getHeight(node->leftC) > getHeight(node->rightC)) { if (node->leftC ->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC)) DoubleRotateLR(node); else leftRotate(node); } } else //如果相等,此节点就是要删除的节点 { if (node->leftC && node->rightC) //此节点有两个儿子 { TreeNode* ptr = node->rightC; //ptr指向节点的右儿子 while (ptr->leftC != NULL) ptr = ptr->leftC;//找到右子树中值最小的节点 //把右子树中最小节点的值赋值给本节点 node->data = ptr->data; //删除右子树中最小值的节点 deleteNode(node->rightC, ptr->data); if (2 == getHeight(node->leftC) - getHeight(node->rightC)) { if (node->leftC->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC)) DoubleRotateLR(node); else leftRotate(node); } } else { TreeNode* ptr = node; //此节点有1个或0个儿子 if (node->leftC == NULL) //有右儿子或者没有儿子 node = node->rightC; else if (node->rightC == NULL) //有左儿子 node = node->leftC; delete ptr; ptr = NULL; } } if (node) node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1; } int main() { TreeNode *head; InitTree(&head); for (int i = 5; i > 0; --i) { Insert((*head).leftC, i); } preOrder((*head).leftC); inOrderTraversal((*head).leftC); cout << endl; deleteNode((*head).leftC, 1); inOrderTraversal((*head).leftC); cout << endl; Insert((*head).leftC, 1); deleteNode((*head).leftC, 4); inOrderTraversal((*head).leftC); cout << endl; preOrder((*head).leftC); return 0; }
相关文章推荐
- JAVA实践自平衡二叉树(AVL树)
- 数据结构之---C语言实现平衡二叉树(AVL树)
- 一步一步写平衡二叉树(AVL树)
- 数据结构——AVL树(平衡二叉树)的详细实现
- poj2418 Hardwood Species(AVL树(平衡二叉树)中序遍历=排序)
- 数据结构与算法系列----平衡二叉树(AVL树)
- Java实现平衡二叉树(AVL树)
- 数据结构之查找(六)——平衡二叉树(AVL树)
- 看数据结构写代码(56) 平衡二叉树(AVL树)
- 平衡二叉树 构造方法
- 大话数据结构—平衡二叉树(AVL树)
- 一步一步写平衡二叉树(AVL树)
- 平衡二叉树(AVL树)
- 平衡二叉树【AVL树】- 通过实例理解概念
- 平衡二叉树(AVL树)
- 一步一步写平衡二叉树(AVL树)
- 平衡二叉树( AVL树 ) (zz)
- 平衡二叉树(AVL树)
- 平衡二叉树(AVL树)
- 平衡二叉树---AVL树的实现