当前位置: 首页 > news >正文

网站建设条件广西壮族自治区

网站建设条件,广西壮族自治区,东莞做网站最好的是哪家,css中文网站模板下载目录 一、AVL树的概念 二、AVL树的定义 三、旋转 四、测试 一、AVL树的概念 二叉搜索树虽然可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化成单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此就有了AVL树&#xf…

目录

一、AVL树的概念

二、AVL树的定义

三、旋转

四、测试


一、AVL树的概念

二叉搜索树虽然可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化成单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此就有了AVL树:当向二叉搜索树中插入新节点后,如果能保证左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即课降低树的高度,从而减少平均搜索长度。

一颗AVL树或者是空树,或者是具有以下性质的二叉搜索树:
它的左右子树都是AVL树

左右子树的高度之差(简称平衡因子)的绝对值不超过1

那为什么是左右高度差不超过1呢

 如果是偶数就做不到完全是0的情况,也就是在某些数量情况下,做不到相等

二、AVL树的定义

template<class K,class V>
struct AVLTreenode
{AVLTreenode<K,V>* _left;AVLTreenode<K, V>* _right;AVLTreenode<K, V>* _parent;pair<K,V> _kv;int _bf;//平衡因子AVLTreenode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_bf(0){}
};
template<class K, class V>
class AVLTree
{typedef AVLTreenode<K, V> Node;
public:private:Node* _root = nullptr;
};

2.1插入

比如说插入在8的左边会导致8的平衡因子更新成0,但是8的父亲是不受影响的

新增节点是可能影响祖先的(子树的高度是否变化)

1.子树的高度不变,就不会继续往上影响祖先

2.反之则会

插入节点如果在9的右边的话,就会影响到8了,至于为什么不在继续往上更新了呢,因为此时这个棵树都不是AVL树了,我们要进行调整

总结 

新增节点在左子树,父亲bf--;

新增节点在右子树,父亲bf++

更新后:

1.父亲的bf更新后==0,父亲所在的子树高度不变,不用再继续往上更新,插入结束了

注:在插入节点之前,父亲bf==1或-1,一边高一边低,新插入节点填上低的那边

2.父亲的bf更新后==1or-1,父亲所在的子树高度变了,不继续往上更新

注:在插入节点之前,父亲==0两边一样高,插入导致高度变化了

3.父亲的 bf更新后==2or-2,此时已经不是AVL树了,违反规则,必须调整处理 

那我们开始处理这个平衡因子 首先我们来判断结束条件,结束条件是由一种情况能看出来的

这样子会一直更新到parent的,所以我们的结束条件也可以判断了

三、旋转

其次我们来处理这个旋转,就是平衡因子为2或者是-2的时候所导致的调整

比如说这种情况

首先旋转我们要注意两个条件

1.左右均衡一些

2.保持搜索树的规则 

我们需要一个压的住两边的父亲,才更新平衡因子 

这是一种比较简单的情况,接下来我们来看一种比较复杂的情况

 我们想3的平衡因子太高了所以我们要把它压下来,压下来我们要找一个压的住的,所以我们选5来做这个,但是5的左边也有一个孩子,我们可以把它往3的右边放(因为它在3的右子树肯定比3大)

这是左单旋的例子,既然有例子,就有概念 

3.1新节点插入较高右子树的右侧-左单旋

 

 

我们着重讲一下2的这一种,a b是x,y,z中任意一种, c必须是x

如果c是y或者z,c的位置要新增,c的位置要不违反avl树,才能继续往上更新,那我们在y的右或者在z的左插入,c是不会向上更新的,在y的左或者z的右插入呢,c就不是avl树了,也不会向上更新,但是我们最终的目的是让10,20变为左单旋,这是不符合的

如果我们把h==2的所有场景穷举出来,就是3*3九种组合

插入位置有4个位置

合计36种情况

但是我们不关注下面的情况,我们只关注10,20那个节点,也就是平衡因子为2的节点我们要把它压下来进行左单旋

	void RoLeft(Node* parent){Node* SubR = parent->_right;Node* SubRL = SubR->_left;parent->_right = SubRL;SubR->_left = parent;if(SubRL)SubRL->_parent = parent;Node* parentParent = parent->_parent;parent->_parent = SubR;if (_root == parent){_root = SubR;SubR->_parent = nullptr;}else {if (parentParent->_left==parent){parentParent->_left = SubR;}else {parentParent->_right = SubR;}SubR->_parent = parentParent;}parent->_bf = SubR->_bf = 0;}

3.2右单旋

	void RoRight(Node* parent){Node* SubL = parent->_left;Node* SubLR = SubL->_right;SubL->_right = parent;parent->_left = SubLR;if (SubLR)SubLR->_parent = parent;Node* parentParent = parent->_parent;parent->_parent = SubL;if (_root == parent){_root = SubL;SubL->_parent = nullptr;}else{if (parentParent->_left==parent){parentParent->_left = SubL;}else{parentParent->_right = SubL;}SubL->_parent = parentParent;}parent->_bf=SubL->_bf=0;}

 那如果我们是在左单旋的左侧位置进行插入呢

3.3右左双旋

这个时候大家可以去画一下图,简单的左单旋已经解决不了这里的问题了 

这时候还要再把b再拆解一下才能解决问题

a和d是高度为h的avl树(h>=0)

b和c是高度为h-1的avl树或者是空树 (h>=1)

这里30就是新增

 

在30的左边或者是右边新增

 h==2也是和左单旋类似一样的道理

总而言之我们可以分为两种情况

一种是h==0,30就是新增

一种是h>=1,在b或者c就是新增

那这两种主要是在平衡因子上的差别

方法:1.40为旋转点进行右单旋

2.20为旋转点进行左单旋

我们先处理局部,30的左边不是高吗我们先处理30的左边,这样就变成了纯粹的右边高

我们再进行一个对20左单旋就可以了 

那我们旋转完成的平衡因子该如何更新 ,这里我们动的是30,20,40因为它们的孩子都动了

双旋在这里是把30推成这棵树的根 ,把30的左边b分给了20的右边(右单旋),把30的右边c分给了40的左边(左单旋),让b,c在30的左右两边

那在c插入也是更上面一样的道理,这里我就不画图了,写一个平衡因子贴在这里,20 -1,30 0,40 0

我们再来画一下h==0的这种情况

我们可以发现这三种情况的平衡因子都是有区别的都需要我们做讨论 

那我们根据什么来区别呢,这里是根据30的平衡因子来区分的,在b插入,30的平衡因子就是-1,

c插入,30的平衡因子就是1,30自己就是新增,平衡因子就是0

那我们先来写一下右左双旋

	void RoRL(Node* parent){Node* SubR = parent->_right;Node* SubRL =SubR->_left;int bf = SubRL->_bf;//因为会不停的变RoRight(SubR);RoLeft(parent);if (bf == 0){parent->_bf = SubR->_bf = SubRL->_bf = 0;}else if (bf == -1){parent->_bf = 0;SubR->_bf = 1;SubRL = 0;}else if (bf == 1){parent->_bf =-1;SubR->_bf = 0;SubRL = 0;}else{assert(false);}}

3.4左右双旋

	void RoLR(Node* parent){Node* SubL = parent->_left;Node* SubLR = SubL->_right;int bf = SubLR->_bf;RoLeft(SubL);RoRight(parent);if (bf == 0){parent->_bf = SubL->_bf = SubLR->_bf = 0;}else if (bf == 1){parent->_bf = 0;SubL->_bf =-1;SubLR = 0;}else if (bf == -1){parent->_bf = 1;SubL->_bf = 0;SubLR = 0;}else{assert(false);}}
bool Insert(const pair<K,V>& kv)
{if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first< kv.first){parent->_right = cur;cur->_parent=parent;}else{parent->_left = cur;cur->_parent = parent;}//旋转while (parent){if (cur==parent->_left){parent->_bf--;}else{parent->_bf++;}if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}else if(parent->_bf == 2 || parent->_bf == -2){//旋转if (parent->_bf == 2 && cur->_bf == 1){RoLeft(parent);}else if(parent->_bf == 2 && cur->_bf == -1){RoRL(parent);}else if(parent->_bf == -2 && cur->_bf == -1){RoRight(parent);}else if (parent->_bf == -2 && cur->_bf == 1){RoLR(parent);}break;}else{assert(false);}}return true;
}

1.旋转让这颗子树平衡了

2.旋转降低了这颗子树的高度,恢复到跟插入以前一样的高度,所以对上一层没有影响,不用更新

	void InOrder(){_InOrder(_root);cout << endl;}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " ";_InOrder(root->_right);}
四、测试
int main()
{int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };AVLTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));}t.InOrder();return 0;
}

 

这个我们只能确定它是搜索树,那怎么判断它是平衡树

2.3判断平衡

	bool IsBalance(){return _IsBalance(_root);}int _Height(Node* root){if (root == nullptr){return 0;}int leftheight= _Height(root->_left);int rightheight = _Height(root->_right);return leftheight > rightheight ? leftheight + 1 : rightheight + 1;}bool _IsBalance(Node* root){if (root == nullptr)return false;int leftheight = _Height(root->_left);int rightheight = _Height(root->_right);if (rightheight - leftheight != root->_bf){cout << root << "->" << "平衡因子异常" << endl;}return abs(leftheight - rightheight) < 2;}

判断平衡因子要注意遵守左右子树高度差不超过1 

int main()
{const int N = 20;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; i++){v.push_back(rand());cout << v.back() << endl;}AVLTree<int, int> t;for (auto e : v){t.Insert(make_pair(e, e));cout << "Insert:" << e << "->" << t.IsBalance() << endl;}cout << t.IsBalance() << endl;return 0;
}

这里是测试代码

 AVL树其实不是很难,但是细节的地方考验的很多,稍微一个不注意就可能引发一连串的报错,所以我们写这类代码的时候很考验我们的耐心,接下来进入红黑树

http://www.cadmedia.cn/news/3715.html

相关文章:

  • 在哪个网站上找超市做生鲜百度网盘官网下载
  • 免费建站平台0网络推广的方式有哪些
  • 青岛公路建设集团有限公司网站网站查询ip地址查询
  • 手机中国网官网百度关键词优化专家
  • 免费设计商标的网站湖南seo优化服务
  • 建站群赚钱有前途吗泰州网站优化公司
  • 制作企业网站的基本步骤网络搭建教程
  • 聊城手机网站建设方案今日新闻大事件
  • 通讯设备 技术支持 东莞网站建设seosem是指什么意思
  • 网站改版不换域名怎么做给公司建网站需要多少钱
  • 有没有做租赁的网站网站如何添加友情链接
  • 外贸公司网站建设 重点是什么指数分布
  • 做dj选歌是哪个网站国际最新十大新闻事件
  • 网站正在建设中单页线下推广公司
  • led高端网站建设大连百度关键词优化
  • 昆明网站设计方案优化网站打开速度
  • 装b神器在线制作sem优化是什么意思
  • 建设网站怎样挣钱自媒体营销的策略和方法
  • web开发是做网站怎么制作一个网站5个网页
  • 网站开发功能清单网站关键词优化方法
  • 鞍山网站制作的网站合肥网站优化公司
  • 重庆网站排名优化公司网站制作多少钱一个
  • 九江网站推广徽hyhyk1怎么开网店
  • 品牌网站设计制作哪家正规成都网站建设
  • 网站设计制作新报价丈哥seo博客工具
  • app运营推广策划方案关键词优化排名软件哪家好
  • 崇礼做网站的公司页面优化的方法有哪些
  • 方又圆网站建设单页面网站如何优化
  • 如何制作漂亮的微信公众号文章seo关键词优化价格
  • 高端网站开发建设杭州seo公司