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

团购网站开发需要多久网站建设文章官网

团购网站开发需要多久,网站建设文章官网,施工企业科技宣传片,重庆网上找工作哪个网站好简介 AVL树是最先被发明出来的自平衡二叉查找树,在1962由前苏联科学家G. M. Adelson-Velsky和E. M. Landis在论文中发表。AVL树中引入了平衡因子,每一个节点都有一个平衡因子(一般是右子树高度 - 左子树高度);AVL树要…

简介

AVL树是最先被发明出来的自平衡二叉查找树,在1962由前苏联科学家G. M. Adelson-Velsky和E. M. Landis在论文中发表。AVL树中引入了平衡因子,每一个节点都有一个平衡因子(一般是右子树高度 - 左子树高度);AVL树要求左右子树高度相差不能超过1,即平衡因子只能是0,1或-1。AVL树的高度始终是log(n),n为节点数量。

AVL树的结构

template<class K,class V>
struct AVLTreeNode   //定义节点的结构
{pair<K, V> _kv;AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;int _bf;//平衡因子balance factorAVLTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _bf(0){}
};template<class K,class V>
class AVLTree
{typdef AVLTreeNode<K, V> Node;
public:private:Node* _root = nullptr;};

_kv是AVL树储存的键值对,既能存储键值key,每一个key也能对应储存一个value值。

为什么要有_parent?

AVL树通过平衡因子来控制树的平衡,插入或删除数据后,需要回溯到父节点计算平衡因子,所以我们需要_parent来储存每一个节点父节点的值。

AVL树的插入 

插入的基本流程

寻找插入的位置

按照二叉树遍历的顺序找到要插入的位置。

更新平衡因子

插入一个新的节点之后,如果父节点的平衡因子发生改变,则需更新从根节点到父节点这条路径的所有节点的平衡因子。

判断是否产生不平衡

如果更新平衡因子之后,没有出现平衡因子不为0,-1,1的,则说明树是平衡的,插入结束。

如果出现了不平衡,对不平衡⼦树旋转,旋转后本质调平衡的同时,本质降低了⼦树的⾼度,不会再影响上⼀层,所以插⼊结束。

平衡因子的更新

更新的原则

平衡因⼦ = 右⼦树⾼度-左⼦树⾼度。
只有⼦树⾼度变化才会影响当前结点平衡因⼦。
插⼊结点,会增加⾼度,所以新增结点在parent的右⼦树,parent的平衡因⼦++,新增结点在
parent的左⼦树,parent平衡因⼦--。
parent所在⼦树的⾼度是否变化决定了是否会继续往上更新。

更新停止的条件

更新后parent的平衡因⼦等于0,更新中parent的平衡因⼦变化为-1->0 或者 1->0,说明更新前
parent⼦树⼀边⾼⼀边低,新增的结点插⼊在低的那边,插⼊后parent所在的⼦树⾼度不变,不会
影响parent的⽗亲结点的平衡因⼦,更新结束。
更新后parent的平衡因⼦等于1 或 -1,更新前更新中parent的平衡因⼦变化为0->1 或者 0->-1,说
明更新前parent⼦树两边⼀样⾼,新增的插⼊结点后,parent所在的⼦树⼀边⾼⼀边低,parent所
在的⼦树符合平衡要求,但是⾼度增加了1,会影响parent的⽗亲结点的平衡因⼦,所以要继续向
上更新。
更新后parent的平衡因⼦等于2 或 -2,更新前更新中parent的平衡因⼦变化为1->2 或者 -1->-2,说
明更新前parent⼦树⼀边⾼⼀边低,新增的插⼊结点在⾼的那边,parent所在的⼦树⾼的那边更⾼
了,破坏了平衡,parent所在的⼦树不符合平衡要求,需要旋转处理,旋转的⽬标有两个:1、把
parent⼦树旋转平衡。2、降低parent⼦树的⾼度,恢复到插⼊结点以前的⾼度。所以旋转后也不
需要继续往上更新,插⼊结束。
不断更新,更新到根,跟的平衡因⼦是1或-1也停⽌了。

插入的整体框架:
 

bool insert(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 (cur->_kv.first < parent->_kv.first){parent->_left = cur;}else if (cur->_kv.first > parent->_kv.first){parent->_right = cur;}cur->_parent = parent;//更新平衡因子while (parent){// 更新平衡因⼦if (cur == parent->_left)parent->_bf--;elseparent->_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){// 不平衡了,旋转处理break;}else{assert(false);}}return true;}

旋转

旋转的原则

1.保持搜索树的规则

2.让树变平衡,降低旋转树的高度

根据插入的位置不同,旋转一共分为四种,左单旋/右单旋/左右双旋/右左双旋

右单旋

右单旋适合处理下图这种情况,插入前,左子树高度刚好比右子树高1,且刚好插入值为在左子树最左边(比原来树中的所有值都小)。

普遍情况:

为了方便理解我们这里取特例: 

插入节点-3之后,树不再平衡。这时候就需要通过旋转来使树再次平衡。怎样让树再次平衡呢?

我们只需要操作最深的那一条路径就好了,让它高度减一,在移到右子树上,这样平衡因子就为0了。

虽然不符合AVL树的规则了,但是这颗树还是符合二叉搜索树的规则的。还是可以中序遍历。

这棵树中序遍历的结果是:-3,1,5,8,10,15。把10拿下来让左子树高度减一,再向办法把10放到右子树中,5的右子树绝对比它的父节点(10)小,所以可以把10变成5的右节点,同时让8接到10的左节点。这样即保证中序遍历的结果又使树恢复了平衡。

代码实现:

//右单旋void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;// 需要注意除了要修改孩⼦指针指向,还是修改⽗亲parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* parentParent = parent->_parent;subL->_right = parent;parent->_parent = subL;// parent有可能是整棵树的根,也可能是局部的⼦树// 如果是整棵树的根,要修改_root// 如果是局部的指针要跟上⼀层链接if (parentParent == nullptr){_root = subL;subL->_parent = nullptr;}else{if (parent == parentParent->_left){parentParent->_left = subL;}else{parentParent->_right = subL;}subL->_parent = parentParent;}parent->_bf = subL->_bf = 0;}

要处理的三个节点

注意:parent不一定是根节点,所以要创建一个临时变量parentParent储存parent的父节点,处理好子树之后,再让subL的父节点指向parentParent(parentParent为空则,subL变为根节点)。

左单旋

左单旋适合一下情况

树中的左旋和右旋互为对称操作,左旋和右旋是可以相互抵消的,即经历一次左旋和一次右旋之后会恢复成原树。

 代码实现:

void RoateL(Node* parent){Node* subR = parent->_right;parent->_right = subR;Node* subRL = subR->_left;if (subRL){subRL->_parent = subR;}Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;parent->_right = subRL;if (subRL){subRL->_parent = parent;}if (parentParent){subR->_parent = parentParent;if (parentParent->_left == parent){subR->_parent = parentParent;parentParent->_left = subR;}else if(parentParent->_right == parent){subR->_parent = parentParent;parentParent->_right = subR;}}else if (parentParent == nullptr){_root = subR;}parent->_bf = subL->_bf = 0;}

左右双旋

观察下面这种情况,它并不是纯粹的左边高,对于节点10是左边高,对于节点5来说是右边高。

这时候单纯的右单旋或者左单旋都不能解决问题, 这时候两次单旋就可以解决问题。以节点5为旋转点,进行一次左单旋,这时候就是一个完全左边高的树结构,完全符合右单旋的应用场景,以节点10为旋转点进行一次右单旋,树恢复平衡。

要处理的节点:

 

 代码实现:

void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == 0){subL->_bf = 0;subLR->_bf = 0;parent->_bf = 0;}else if (bf == -1){subL->_bf = 0;subLR->_bf = 0;parent->_bf = 1;}else if (bf == 1){subL->_bf = -1;subLR->_bf = 0;parent->_bf = 0;}else{assert(false);}}

右左双旋 


右左双旋于左右双旋类似,接下来我们以普适情况抽象出a,b,c三棵子树来讨论。另外我们需要把b⼦树的 细节进⼀步展开为12和左⼦树⾼度为h-1的e和f⼦树,因为我们要对b的⽗亲15为旋转点进⾏右单旋,右单旋需要动b树中的右⼦树。

b⼦树中新增结点的位置不同,平衡因⼦更新的细节也不同,通过观察12的平衡因⼦不同,这⾥我们要分三个场景讨论。
场景一: h >= 1时,新增结点插⼊在e⼦树,e⼦树⾼度从h-1变为h并不断更新12->15->10平衡因
⼦,引发旋转,其中12的平衡因⼦为-1,旋转后10和12平衡因⼦为0,15平衡因⼦为1。

 场景二:h >= 1时,新增结点插⼊在f⼦树,f⼦树⾼度从h-1变为h并不断更新12->15->10平衡因⼦, 引发旋转,其中12的平衡因⼦为1,旋转后15和12平衡因⼦为0,10平衡因⼦为-1。

场景三:h == 0时,a/b/c都是空树,b⾃⼰就是⼀个新增结点,不断更新15->10平衡因⼦,引发旋 转,其中12的平衡因⼦为0,旋转后10和12和15平衡因⼦均为0。

 

代码实现:

void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subR->_bf = 0;subRL->_bf = 0;parent->_bf = 0;}else if (bf == 1){subR->_bf = 0;subRL->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;subRL->_bf = 0;parent->_bf = 0;}else{assert(false);}}

 查找

按照遍历二叉树的逻辑查找即可。

Node* Find(const K& key)//按照键值查找{Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}

AVL树平衡检测

对于实现的AVL树是否合格,我们通过判断左右子树高度差来判断,即判断平衡因子。

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 _IsBalanceTree(Node* root){// 空树也是AVL树if (nullptr == root)return true;// 计算pRoot结点的平衡因⼦:即pRoot左右⼦树的⾼度差int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);int diff = rightHeight - leftHeight;// 如果计算出的平衡因⼦与pRoot的平衡因⼦不相等,或者// pRoot平衡因⼦的绝对值超过1,则⼀定不是AVL树if (abs(diff) >= 2){cout << root->_kv.first << "⾼度差异常" << endl;return false;}if (root->_bf != diff){cout << root->_kv.first << "平衡因⼦异常" << endl;return false;}// pRoot的左和右如果都是AVL树,则该树⼀定是AVL树return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);}


文章转载自:

http://cGYCRC1W.qgmwt.cn
http://SxqNmI9Y.qgmwt.cn
http://s3LmWafk.qgmwt.cn
http://Ki7krExU.qgmwt.cn
http://rhDXjDv2.qgmwt.cn
http://aWjm5YIn.qgmwt.cn
http://0AvnNLgH.qgmwt.cn
http://xg0NijbT.qgmwt.cn
http://FcuvviYP.qgmwt.cn
http://S7ivXxPR.qgmwt.cn
http://eNfWcxxO.qgmwt.cn
http://kYZj2zqS.qgmwt.cn
http://1eU3Bdae.qgmwt.cn
http://PWOeZAep.qgmwt.cn
http://PUOORT0G.qgmwt.cn
http://4PE8W1m1.qgmwt.cn
http://YHgF4Up6.qgmwt.cn
http://VHEVZ5JY.qgmwt.cn
http://BuJEXvHk.qgmwt.cn
http://LtcMXiQd.qgmwt.cn
http://U8d0vYPj.qgmwt.cn
http://GJaNjkJc.qgmwt.cn
http://I95WpaTx.qgmwt.cn
http://Gxa7nv4t.qgmwt.cn
http://9OJd9q4q.qgmwt.cn
http://pFIkJg2X.qgmwt.cn
http://rx4jzhDZ.qgmwt.cn
http://V1YL2kPc.qgmwt.cn
http://GQ8kVFpI.qgmwt.cn
http://08SN0UkH.qgmwt.cn
http://www.dtcms.com/wzjs/667183.html

相关文章:

  • 申请域名后怎么建设网站我想承包小工程
  • 那个相亲网站做的比较好网络架构分为几层
  • 个人网站设计流程图简单的页面
  • 池州家居网站建设怎么样线上推广渠道有哪些
  • 手机网站开发与pc网站开发的不同怎么做网站广告位
  • 包头公司做网站淮南最新消息今天
  • 服务器在国外的网站现在网站后台有哪几种模板形式
  • jsp网站建设作业我的网站wordpress
  • 住房和城乡建设部网站投诉电话域名绑定wordpress
  • 百度指数免费查询入口沈阳网站推广优化公司
  • 建设网站涉及哪些问题网页传奇新开网站
  • 网站后台超链接怎么做做网站是什么
  • 网站发布工具百度知道网页版地址
  • 抚顺网站seo凡科快图官网下载
  • 做网站排名工具沈阳男科医院十大排名
  • 北京网站建设认知网站域名会赠送几个邮箱
  • 上海做网站天锐工程建设动态管理网站
  • 邢台做wap网站多少钱html5开发微网站
  • 怎么做好网站推广静态网站开发考虑什么
  • 网站建设培训公司付费推广途径与原因
  • 玉溪网站建设现状宁波北仑做网站
  • 公司宣传网站建站怎么用网站卖自己做
  • 网站当前位置 样式邯郸网站设计定制
  • 宜宾网站建设哪家好wordpress 插件 喜欢
  • 做微商童装网站电子商务网站系统开发
  • 做品牌的人常用的网站wordpress rest 授权
  • 工业园网站建设黑客收徒网站建设
  • 网站改版文案微信公众号平台官网入口
  • 未成年人思想道德建设网站wordpress 多级菜单插件
  • 用ps做企业网站分辨率是多少钱商洛市城乡建设局网站