AVL树详解&面试题-判断一棵树是否是平衡二叉树
来源:互联网 发布:策略经营单机手游 知乎 编辑:程序博客网 时间:2024/06/04 19:34
上次写了关于二叉搜索树的分析,但是二叉搜索树有一个缺陷,就是当插入一个有序(或接近有序)的序列时,二叉搜索树就相当于一个链表了,搜索效率会特别低。那么,如何来改进呢?这就引入了AVL树(高度平衡二叉树),那么下面我们一起来了解一下AVL树吧!
AVL树的特征:
1、左右子树的高度差都不超过1;
2、左右子树都是AVL树;
3、每个节点都有一个平衡因子bf(blance fator ),其值为右子树的高度减去左子树的高度。
AVL树也是二叉搜索树,只是在插入节点时,进行了一些调整,使它的把树的高度降下来,做右子树高度差不超过1。做怎样的调整呢?这就要看一下AVL树的旋转啦!
当插入一个节点后,树的平衡因子bf=2时就对该树进行旋转,旋转又分为如下几种情况:
AVL树的旋转:
下面我给出我写的代码,只实现了插入操作,删除操作后期会加进来。
代码实现AVL树&判断一棵树是否是平衡二叉树:
#include<iostream>using namespace std;template<class K, class V>struct AVLTreeNode{ K _key; V _value; int _bf; //平衡因子 AVLTreeNode * _parent; AVLTreeNode * _left; AVLTreeNode * _right; AVLTreeNode(K k=K(),V v=V()) :_key(k) ,_value(v) ,_bf(0) ,_parent(NULL) ,_left(NULL) ,_right(NULL) {}};template<class K,class V>class AVLTree{ typedef AVLTreeNode<K, V> Node;public: AVLTree() :_root(NULL) {} bool Insert(const K key,const V value) { Node * cur = _root; Node * parent = NULL; if (cur == NULL)//_root为空/空树 { _root = new Node(key, value); _root->_bf = 0; _root->_parent = NULL; return true; } while (cur)//找插入节点位置节 { if (cur->_key < key) { parent = cur; cur = cur->_right; } else if (cur->_key > key) { parent = cur; cur = cur->_left; } else//key值已存在,更新该key值得value { cur->_value = value; return true; } } //插入节点 Node * node = new Node(key, value); if (parent->_key > key) { parent->_left = node; node->_parent = parent; node->_bf = 0; } else { parent->_right = node; node->_parent = parent; node->_bf = 0; } //更新平衡因子 cur = node; while (parent) { if (parent->_left == cur) { parent->_bf--; } else if(parent->_right==cur) { parent->_bf++; } //根据平衡因子判断是否需要再调整祖先节点的平衡因子或调整树 if (parent->_bf == 0) { break; } else if (parent->_bf == 1 || parent->_bf == -1) { cur = parent; parent = cur->_parent; } //如果不满足AVL树的性质,则旋转调整 else if (parent->_bf == -2) { if (parent->_left->_bf == -1) { RotateR(parent->_left);//向右单旋 } else if(parent->_left->_bf ==1) { RotateLR(parent->_left);//左右双旋(先左单旋再向右单旋) } else { printf("平衡因子异常\n"); return false; } } else if (parent->_bf == 2) { if (parent->_right->_bf == 1) { RotateL(parent->_right);//向左单旋 } else if(parent->_right->_bf==-1) { RotateRL(parent->_right);//右左双旋(先右单旋,再左单旋) } else { printf("平衡因子异常\n"); return false; } } else { printf("平衡因子异常\n"); return false; } } } int Height()//求二叉树的高度 { return _Height(_root); } int Height(Node * root) { return _Height(root); } bool IsBlance()//判断一棵二叉树是否是平衡二叉树 { return _IsBlance(_root); } void InOrder()//中序遍历树 { _InOrder(_root); cout << endl; }protected: void RotateL(Node * root)//向左单旋 { Node *parent = root->_parent; Node *subL = root->_left; parent->_right = subL; if (subL) { subL->_parent = parent; } if (parent == _root) { _root = root; root->_parent = NULL; } else { if (parent->_parent->_left == parent) { parent->_parent->_left = root; } else { parent->_parent->_right = root; } root->_parent = parent->_parent; } root->_left = parent; parent->_parent = root; if (subL) { subL->_bf = 0; } parent->_bf = root->_bf = 0; } void RotateR(Node * root)//向右单旋 { Node * parent = root->_parent; Node * subR = root->_right; parent->_left = subR; if (subR) { subR->_parent = parent; } if (parent == _root) { _root = root; root->_parent = NULL; } else { root->_parent = parent->_parent; if (parent->_parent->_left == parent) { parent->_parent->_left = root; } else { parent->_parent->_right = root; } } root->_right = parent; parent->_parent = root; if (subR) { subR->_bf = 0; } root->_bf = parent->_bf = 0; } void RotateLR(Node * root)//左右双旋 { RotateL(root->_right); RotateR(root->_parent); Node* cur = root->_parent; if (cur->_bf == 0) { cur->_left->_bf = 0; cur->_right->_bf = 0; } else if(cur->_bf == 1) { cur->_bf = 0; cur->_left->_bf = -1; cur->_right->_bf = 0; } else if (cur->_bf == -1) { cur->_bf = 0; cur->_left->_bf = 0; cur->_right->_bf = 1; } else { printf("平衡因子异常\n"); return; } } void RotateRL(Node*root) { RotateR(root->_left); RotateL(root->_parent); Node* cur = root->_parent; if (cur->_bf == 0) { cur->_left->_bf = 0; cur->_right->_bf = 0; } else if (cur->_bf == 1) { cur->_bf = 0; cur->_left->_bf = -1; cur->_right->_bf = 0; } else if (cur->_bf == -1) { cur->_bf = 0; cur->_left->_bf = 0; cur->_right->_bf = 1; } else { printf("平衡因子异常\n"); return; } } int _Height(Node * root) { if (root == NULL) { return 0; } int left = _Height(root->_left) + 1; int right = _Height(root->_right) + 1; return left > right ? left : right; } bool _IsBlance(Node * root) { if (root == NULL) { return true; } int left = Height(root->_left); int right = Height(root->_right); if (abs(right - left) != abs(root->_bf)) { cout << "平衡因子错误\n" << endl; return false; } return (abs(right - left) < 2) && _IsBlance(root->_left) && _IsBlance(root->_right); } void _InOrder(Node * root) { if (root == NULL) { return; } _InOrder(root->_left); cout << "key:" << root->_key << "value:" << root->_value<<" "; _InOrder(root->_right); }private: Node * _root;};
阅读全文
0 0
- AVL树详解&面试题-判断一棵树是否是平衡二叉树
- 判断一个二叉树是否是平衡二叉树(AVL)
- 面试题——判断一棵树是否是平衡二叉树
- 面试题39:获得二叉树深度和判断是否是平衡二叉树
- 数据结构面试题/判断一棵二叉树是否是平衡二叉树
- 【IT笔试面试题整理】判断一个二叉树是否是平衡的?
- 判断一棵树是否是平衡二叉树
- 判断一棵树是否是平衡二叉树
- 判断一棵树是否是平衡二叉树
- [各种面试题] 判断是否平衡二叉树
- 面试题39(2). 判断是否为平衡二叉树
- 数据结构之如何判断一棵二叉树是否是平衡二叉树(AVL树)
- 如何判断一棵二叉树是否是平衡二叉树(AVL)
- 数据结构面试题/判断一棵树是否是完全二叉树
- 面试题09 从二叉树的深度扩展到判断是否是二叉平衡树 【树】 Dserving thinking
- 剑指Offer系列-面试题39-2:判断一棵树是否为平衡二叉树
- 面试题39:平衡二叉树判断
- 判断二叉树是否是平衡树
- CentOS7.3编译安装NodeJS6.10
- 【mybatis】:mybatis中$和#符号的区别与联系
- 计算机网络:端到端原则对互联网的影响与面临的问题
- D_D系统构建-MBR(1)
- 线程池
- AVL树详解&面试题-判断一棵树是否是平衡二叉树
- [paper] Co-CNN
- Centos-Tomcat配置APR
- 线性表
- C# DataSet和DataTable详解
- java 日期转换校验
- Java+Selenium3方法篇24-单选和多选按钮操作
- SQL:结构化查询语言(Structured Query Language)。
- 【GregorianCalendar】格林尼治时间GregorianCalendar[]解密