数据结构之平衡二叉树AVL
2013-11-11 21:38
525 查看
平衡二次树AVL:是二叉查找树的改进版,不会像二叉查找树一样,在碰到序列有序是糟糕成达到O(n),平很二叉树在每次插入的时候,都会试图检查左右子树的高度差是不超过1(包括1),如果超过了,就会调整树的结构,使树一直保持平衡,以至于达到非常好的效率,O(logn).
#include <iostream> using namespace std; typedef struct BBNode { int m_data; // 平衡因子,如果【左子树的深度】减去【右子树的深度】,右因为平衡二叉树左右子树的深度查不超过1(包括一),所以factor的值为【-1, 0, 1】 int m_factor; BBNode* m_lchild; BBNode* m_rchild; }BBNode, *BBSTree;
/* a b / / \ b => c a / c */ // 向右旋转 void R_Rotate(BBSTree& tree) { // 左孩子 BBNode* lchild = tree->m_lchild; // 【左孩子】已经有指针指向了,所以可以指向别的地方了,那么就指向根【左孩子】的【右孩子】 tree->m_lchild = lchild->m_rchild; // 【左孩子】的【右孩子】已经有指针指向了,那么可以指向根结点了 lchild->m_rchild = tree; tree = lchild; }
/* a b \ / \ b => a c \ c */ // 向左旋转 void L_Rotate(BBSTree& tree) { BBNode* rchild = tree->m_rchild; tree->m_rchild = rchild->m_lchild; rchild->m_lchild = tree; tree = rchild; }
/* a a c / / / \ b => c => b a \ / c b */ // 调整左子树的平衡 // 1:单旋转-右旋转 // 2: 双旋转-【左子树】先左旋转-再右旋转 void LeftBalance(BBSTree& tree) { BBNode* lchild = tree->m_lchild; // 如果是偏向一边的(根->左孩子->左孩子),只需要单旋转 if (lchild->m_factor == 1) { tree->m_factor = 0; lchild->m_factor = 0; R_Rotate(tree); } // 如果不是偏向一边(根->左孩子->右孩子),则需要双选 // 即先将【左子树】左旋转,再将树右旋转 else if (lchild->m_factor == -1) { BBNode* lchild_rchild = lchild->m_rchild; // 修改【根结点】和【左孩子】的【平衡因子】 switch (lchild_r bdc6 child->m_factor) { case -1: { tree->m_factor = 0; lchild->m_factor = 1; }break; case 0: { tree->m_factor = 0; lchild->m_factor = 0; }break; case 1: { tree->m_factor = -1; lchild->m_factor = 0; }break; } lchild_rchild->m_factor = 0; L_Rotate(lchild); R_Rotate(tree); } }
/* a a c \ \ / \ b => c => a b / \ c b */ // 调整右子树的,两种情况 // 1:只需要单旋转-左旋转 // 2: 双旋转-【右子树】先右旋转-再左旋转 void RightBalance(BBSTree& tree) { BBNode* rchild = tree->m_rchild; // 如果是偏向一边的(根->右孩子->右孩子) if (rchild->m_factor == -1) { tree->m_factor = 0; rchild->m_factor = 0; L_Rotate(tree); } // 如果不是偏向一边的(根->右孩子->左孩子) else if (rchild->m_factor == 1) { BBNode* rchild_lchild = rchild->m_lchild; switch (rchild_lchild->m_factor) { case -1: { tree->m_factor = 1; rchild->m_factor = 0; }break; case 0: { tree->m_factor = 0; rchild->m_factor = 0; }break; case 1: { tree->m_factor = 0; rchild->m_factor = -1; }break; } rchild_lchild->m_factor = 0; L_Rotate(rchild); R_Rotate(tree); } }
// @tree:平衡二叉树 // @e:要插入的元素 // @taller:是否增高了 int insertAVL(BBSTree& tree, int e, bool& taller) { // 如果tree不存,则在此处插入结点 if (!tree) { BBNode* node = new BBNode; node->m_data = e; node->m_factor = 0; //新结点没有左右孩子,factor自然为0 node->m_lchild = 0; node->m_rchild = 0; tree = node; // 只要是新结点,taller都标记为true,但是它实际上存在着下面三种情况的: // 1:如果父节点没有左右孩子,则插入node,真的右增高 // 2:如果父节点存在左孩子,插入node作为右孩子,则实际上并未增高 // 3:如果父节点存在右孩子,插入node作为左孩子,则实际上并未增高 // 但是这些都留待上一层的函数里去处理 taller = true; } else { // 要插入的元素小于当前结点 if (e < tree->m_data) { // 将元素插入到当前结点的左子树中 if (!insertAVL(tree->m_lchild, e, taller)) { // 如果插入失败 return 0; } // 子树是不是增高了 if (taller) { switch (tree->m_factor) { // 如果之前【右子树】高于【左子树】 case -1: { // 因为插入的是【左子树】,所以两边的深度相等了 tree->m_factor = 0; // 当然,因为插入元素之后,高度不变 taller = false; }break; // 如果之前【左子树】高度等于【右子树】 case 0: { // 因为插入的是【左子树】,所以当前【左子树】高于【右子树】 // 但是还未超过【平衡二叉树】【左右子树】高度差不大于1的限制 tree->m_factor = 1; taller = true; } // 如果之前【左子树】高度大于【右子树】 case 1: { // 当前插入的是【左子树】,所以当前【左子树】高于了【右子树】, // 并且超过了【平衡二叉树】【左右子树】高度差不大于1的限制 // 所以要调整下 LeftBalance(tree); taller = false; } } // switch } // if(taller) } else if (e == tree->m_data) { return 0; } else { if (!insertAVL(tree->m_rchild, e, taller)) { return 0; } if (taller) { switch(tree->m_factor) { // 如果之前【左子树】低于【右子树】 case -1: { // 因为当前插入的是【右子树】,所以【右子树】的高度 // 超过了【平衡二次树】的【左右子树】深度差不超过1的限制 // 所以要调整下 RightBalance(tree); taller = false; }break; // 如果之前【左子树】高度等于【右子树】 case 0: { // 因为当前插入的是【右子树】,所以【右子树】的高度增高了, // 但是不会超过【平衡二次树】的【左右子树】深度差不超过1的限制 tree->m_factor = -1; taller = true; }break; // 如果之前【左子树】高于【右子树】 case 1: { // 因为当前插入的是【右子树】,所以两边的高度相等了 tree->m_factor = 0; taller = false; }break; } } } // else } // else return 1; }
// 中序遍历 void orderTraver(BBSTree tree) { if (tree) { orderTraver(tree->m_lchild); cout<<tree->m_data<<" "; orderTraver(tree->m_rchild); } }
int main() { BBSTree tree = 0; bool taller; insertAVL(tree, 1, taller); insertAVL(tree, 2, taller); insertAVL(tree, 3, taller); insertAVL(tree, 4, taller); insertAVL(tree, 5, taller); insertAVL(tree, 6, taller); orderTraver(tree); return 0; }
相关文章推荐
- AVL树
- 平衡二叉树的数组表示算法
- 基本数据结构之AVL树-简单实现
- 基本数据结构之AVL树
- AVL树的插入删除查找算法实现和分析-2(树高度法)
- 平衡二叉树(AVL树)
- 平衡二叉树(AVL)--查找、删除、插入(Java实现)
- 非线性数据结构 之 AVL树(1)
- 非线性数据结构 之 AVL树(2)
- [互联网面试笔试汇总C/C++-16] 判断一棵二叉树是否是平衡二叉树
- 平衡二叉树判断
- 数据结构 - 平衡二叉树
- 一步一步从二叉查找树学到红黑树
- 查找算法总结(二)
- AVL Operation
- 平衡二叉树(AVL)
- AVL树的C++实现
- 平衡二叉树——AVL树的实现
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)