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

更改了网站关键词后要怎么做公司网站域名续费一年多少钱

更改了网站关键词后要怎么做,公司网站域名续费一年多少钱,河北邢台wap网站建设,网站备案和icp备案文章目录 前言AVL树节点的定义AVL树的插入AVL树的旋转AVL树的验证AVL树的删除AVL树的性能与源码 前言 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此&…

文章目录

  • 前言
  • AVL树节点的定义
  • AVL树的插入
  • AVL树的旋转
  • AVL树的验证
  • AVL树的删除
  • AVL树的性能与源码




前言


二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson - Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:

  • 它的左右子树都是AVL树
  • 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)

在这里插入图片描述
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在 O ( l o g 2 n ) O(log_2 n) O(log2n),搜索时间复杂度O( l o g 2 n log_2 n log2n)。


AVL树节点的定义


	template<class T>struct TreeNode{public:TreeNode(T data):_data(data), _bf(0), _parent(nullptr), _left(nullptr), _right(nullptr){}public:T _data;// Defining balance factorint _bf;  // 该节点的平衡因子// 定义成一个三叉链结构,方便后续操作TreeNode* _parent;  // 该节点的双亲TreeNode* _left;  // 该节点的左孩子TreeNode* _right;  // 该节点的右孩子};


AVL树的插入


因为插入逻辑比较复杂,我在这里就写一个大致思路,具体代码我上传到了git上。

AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步:

  1. 按照二叉搜索树的方式插入新节点
  2. 调整节点的平衡因子

此处我写一个大致的代码逻辑,并结合图片给大家看一下:

bool Insert(const T& data)
{// 1. 先按照二叉搜索树的规则将节点插入到AVL树中// ...// 2. 新节点插入后,AVL树的平衡性可能会遭到破坏,此时就需要更新平衡因子,// 并检测是否破坏了AVL树的平衡性/*cur插入后,parent的平衡因子一定需要调整,在插入之前,parent的平衡因子分为三种情况:-1,0, 1, 插入时出现以下两种情况:1. 如果cur插入到parent的左侧,只需给parent的平衡因子-1即可2. 如果cur插入到pParent的右侧,只需给parent的平衡因子+1即可此时:parent的平衡因子可能有三种情况:0,正负1, 正负21. 如果parent的平衡因子为0,说明插入之前pParent的平衡因子为正负1,插入后被调整成0,此时满足AVL树的性质,插入成功2. 如果parent的平衡因子为正负1,说明插入前parent的平衡因子一定为0,插入后被更新成正负1,此时以pParent为根的树的高度增加,需要继续向上更新3. 如果parent的平衡因子为正负2,则parent的平衡因子违反平衡树的性质,需要对其进行旋转处理*/while (parent){// 更新双亲的平衡因子if (cur == parent->_pLeft)parent->_bf--;elseparent->_bf++;// 更新后检测双亲的平衡因子if (0 == parent->_bf){break;}else if (1 == pParent->_bf || -1 == pParent->_bf){// 插入前双亲的平衡因子是0,插入后双亲的平衡因为为1 或者 -1 ,说明以双亲为根的二叉树// 的高度增加了一层,因此需要继续向上调整cur = pParent;pParent = pCur->_pParent;}else{// 双亲的平衡因子为正负2,违反了AVL树的平衡性,需要对以parent// 为根的树进行旋转处理if (2 == pParent->_bf){// ...}else{// ...}}}return true;
}

在这里插入图片描述

插入节点会影响新增节点的部分祖先,
更新规则:

  • c是p的左边,p->_bf--
  • c是p的右边,p->_bf++

是否要继续更新取决于p的高度是否变化,是否会影响爷爷节点。

在上面这张图的基础上,插入11:
请添加图片描述
我们可以看到:

  • 更新后,p->_bf == 0,p所在的高度不会改变,不会影响爷爷节点。说明更新前,p->_bf是1或者-1,p的矮的那一边插入了新节点,左右高度均衡了,p的高度不变,不会影响爷爷,更新结束。
  • 更新后,p->_bf == 1 / -1,p所在的子树高度变了,会影响爷爷。说明更新前,p->_bf是0,p的有一边插入,p变得不均衡,但不违反规则,p的高度变了,会影响爷爷,继续往上更新

在上面这张图的基础上,再插入1:
在这里插入图片描述

  • 更新后,p->_bf == 2 / -2,说明p所在的子树违反了平衡规则,需要进行旋转处理。


AVL树的旋转


如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:

1. 新节点插入较高左子树的左侧—左左:右单旋
在这里插入图片描述

/*上图在插入前,AVL树是平衡的,新节点插入到30的左子树(注意:此处不是左孩子)中,30左子树增加了一层,导致以60为根的二叉树不平衡,要让60平衡,只能将60左子树的高度减少一层,右子树增加一层,即将左子树往上提,这样60转下来,因为60比30大,只能将其放在30的右子树,而如果30有右子树,右子树根的值一定大于30,小于60,只能将其放在60的左子树,旋转完成后,更新节点的平衡因子即可。在旋转过程中,有以下几种情况需要考虑:1. 30节点的右孩子可能存在,也可能不存在2. 60可能是根节点,也可能是子树如果是根节点,旋转完成后,要更新根节点如果是子树,可能是某个节点的左子树,也可能是右子树大家在此处可举一些详细的例子进行画图,考虑各种情况,加深旋转的理解
*/
void RotateR(Node* parents)
{// SubL: parents的左孩子// SubLR: parents左孩子的右孩子,注意:该节点可能为空Node* SubL = parents->_left;Node* SubLR = SubL->_right;// 旋转完成之后,30的右孩子作为双亲的左孩子parents->_left = SubLR;// 如果30的左孩子的右孩子存在,更新该节点的双亲if (SubLR != nullptr)SubLR->_parent = parents;// 60 作为 30的右孩子SubL->_right = parents;// 因为60可能是棵子树,因此在更新其双亲前必须先保存60的双亲Node* ppnode = parents->_parent;// 更新60的双亲	parents->_parent = SubL;// 更新30的双亲SubL->_parent = ppnode;// 如果60是根节点,更新指向根节点的指针if (_root == parents){_root = SubL;SubL->_parent = nullptr;}else{ // 如果60是子树,可能是其双亲的左子树,也可能是右子树if (parents == ppnode->_left)ppnode->_left = SubL;elseppnode->_right = SubL;}// Renewal balance factorparents->_bf = 0;SubL->_bf = 0;
}

2. 新节点插入较高右子树的右侧—右右:左单旋

在这里插入图片描述
实现及情况考虑可参考右单旋:

void RotateL(Node* parents)
{Node* SubR = parents->_right;Node* SubRL = SubR->_left;parents->_right = SubRL;if (SubRL != nullptr)SubRL->_parent = parents;SubR->_left = parents;Node* ppnode = parents->_parent;parents->_parent = SubR;SubR->_parent = ppnode;if (_root == parents){_root = SubR;SubR->_parent = nullptr;}else{if (parents == ppnode->_left)ppnode->_left = SubR;elseppnode->_right = SubR;}// Renewal balance factorparents->_bf = 0;SubR->_bf = 0;
}

3. 新节点插入较高左子树的右侧—左右:先左单选再右单旋
在这里插入图片描述
将双旋变成单旋后再旋转,即:先对30进行左单旋,然后再对90进行右单旋,旋转完成后再考虑平衡因子的更新。
旋转之前先看60的平衡因子是多少,旋转结束以后,根据60的平衡因子更新结果。
这里平衡因子的更新有三种情况:

  1. 旋转之前,60的平衡因子为-1
    在这里插入图片描述

  2. 旋转之前,60的平衡因子为1
    在这里插入图片描述

  3. 旋转之前,60的平衡因子为0
    在这里插入图片描述

从这三张图中,可以发现,不管旋转之前60的平衡因子是多少,最后都会变成0(在单旋中,已经将它置0),所以我们只用观察30,90 的平衡因子。而不管这棵树怎么变,它必定会遵守搜索二叉树的规则,所以在这里我只是用了一个示例向大家展示这三种情况。不管这棵树的形状是什么样的,只要它满足搜索二叉树的规则,那么左右双旋只会有这几种情况。

// 旋转之前,60的平衡因子可能是-1/0/1,旋转完成之后,根据情况对其他节点的平衡因子进行调整
void RotateLR(Node* parents)
{Node* SubL = parents->_left;Node* SubLR = SubL->_right;// 旋转之前,保存pSubLR的平衡因子,旋转完成之后,需要根据该平衡因子来调整其他节点的平衡因子int bf = SubLR->_bf;// 先对30进行左单旋RotateL(SubL);// 再对90进行右单旋RotateR(parents);// Renewal balance factorif (bf == 0){parents->_bf = 0;SubL->_bf = 0;}else if (bf == 1){parents->_bf = 0;SubL->_bf = -1;}else if (bf == -1){parents->_bf = 1;SubL->_bf = 0;}
}

4. 新节点插入较高右子树的左侧—右左:先右单旋再左单旋

在这里插入图片描述

这里与左右双旋相似,将双旋变成单旋后再旋转,即:先对90进行右单旋,然后再对30进行左单旋,旋转完成后再考虑平衡因子的更新。
旋转之前先看60的平衡因子是多少,旋转结束以后,根据60的平衡因子更新结果。
这里平衡因子的更新有三种情况:

  1. 旋转之前,60的平衡因子为1
    在这里插入图片描述

  2. 旋转之前,60的平衡因子为-1
    在这里插入图片描述

  3. 旋转之前,60的平衡因子为0
    在这里插入图片描述

void RotateRL(Node* parents)
{Node* SubR = parents->_right;Node* SubRL = SubR->_left;int bf = SubRL->_bf;RotateR(SubR);RotateL(parents);// Renewal balance factorif (bf == 0){parents->_bf = 0;SubR->_bf = 0;}else if (bf == 1){parents->_bf = -1;SubR->_bf = 0;}else if (bf == -1){parents->_bf = 0;SubR->_bf = 1;}
}

总结
假如以parent为根的子树不平衡,即parent的平衡因子为2或者-2,分以下情况考虑

  1. parent的平衡因子为2,说明parent的右子树高,设parent的右子树的根为SubR
    当SubR的平衡因子为1时,执行左单旋
    当SubR的平衡因子为-1时,执行右左双旋
  2. parent的平衡因子为-2,说明parent的左子树高,设parent的左子树的根为SubL
    当SubL的平衡因子为-1时,执行右单旋
    当SubL的平衡因子为1时,执行左右双旋
    旋转完成后,原parent为根的子树个高度降低,已经平衡,不需要再向上更新。

AVL树的旋转只有以上情况,不可能会出现其他情况了。


AVL树的验证


AVL树是在二叉搜索树的基础上加入了平衡性的限制,因此要验证AVL树,可以分两步:

  1. 验证其为二叉搜索树
    如果中序遍历可得到一个有序的序列,就说明为二叉搜索树
  2. 验证其为平衡树
    • 每个节点子树高度差的绝对值不超过1(注意节点中如果没有平衡因子)
    • 节点的平衡因子是否计算正确
bool Isbalance()
{int Hight = 0;return _Isbalance(_root, Hight);
}
// 为了提高效率,可以走后序来计算每个节点的左子树和右子树的高度差为多少
// 通过Hight来保存每个节点的最高的子树的高度为多少
bool _Isbalance(Node* root, int& Hight)
{if (root == nullptr)return true;int leftHight = 0;int rightHight = 0;if (!_Isbalance(root->_left, leftHight) || !_Isbalance(root->_right, rightHight)){// 如果root的左子树或者右子树不平衡,就直接返回falsereturn false;}// 判断每个节点的左右子树高度差的绝对值不超过1if (abs(rightHight - leftHight) >= 2){std::cout << "balance factor error, the tree is unbalanced\n";return false;}// 判断每个节点的右子树的最大高度与左子树的最大高度的差值是否等于该节点的平衡因子else if (rightHight - leftHight != root->_bf){std::cout << root->_data << " the balance factor is wrong\n";return false;}// 保存左子树和右子树较高的高度Hight = leftHight > rightHight ? leftHight + 1 : rightHight + 1;return true;
}

在这里插入图片描述
这段代码是随机生成10000个数,插入到我自己写的一棵AVL树中,插完这10000个树以后,我对这棵树进行了一下判断是否平衡,结果是平衡的,证明我的插入逻辑是没有问题的(我测试了不止这一组数据)。


AVL树的删除


因为插入删除比较复杂,我在这里就写一个大致思路,具体代码我上传到了git上。

因为AVL树也是二叉搜索树,可按照二叉搜索树的方式将节点删除,然后再更新平衡因子,只不
过与插入不同的是,删除节点后的平衡因子更新,最差情况下一直要调整到根节点的位置。

这里更新平衡因子的逻辑与插入更新平衡因子的逻辑恰恰是相反的。

在这里插入图片描述

删除节点会影响删除节点的部分祖先(如果是删除根节点,也会找一个可以替代的节点交换值再删除,具体可以参考搜索二叉树的删除部分)。
更新原则:

  • c是p的左边,p->_bf++
  • c是p的右边,p->_bf--

是否要继续更新取决于p的高度是否变化,是否会影响爷爷节点。

在上面这张图的基础上,删除7:
在这里插入图片描述
在上面这张图的基础上,再删除3:
在这里插入图片描述
在上面这张图的基础上,再删除14:
在这里插入图片描述

从上面三个动图可以分析出:

  • 更新后p->_bf == 1 / -1,p所在的子树高度不变,不会影响爷爷。说明更新前,p->_bf是0,p的两边是均衡的,p的有一边删除了,p变得不均衡,但不违反规则,p的高度不变,不会影响爷爷,更新结束。
  • 更新后,p->_bf == 0,p所在的子树的高度变了,会影响爷爷。说明更新前,p->_bf == 1 / -1,p的有一边删除了,p的左右变得均衡,p的高度变了,会影响爷爷,继续往上更新。
  • 更新后,p->_bf == 2 / -2,说明p所在的子树违反了平衡规则,需要进行旋转处理。


AVL树的性能与源码


AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即 l o g 2 ( N ) log_2(N) log2(N)。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。

源码地址:https://gitee.com/ASL498/data-structure/tree/master/AVLTree

http://www.khdw.cn/news/1817.html

相关文章:

  • 中国建设工程人才库官方网站威海百度seo
  • 做网站推广引流效果好吗西安seo外包优化
  • 泛华建设集团网站百度竞价教程
  • 长垣县做网站的百度seo排名公司
  • 高唐网站建设服务商网络营销推广8种方法
  • 企业门户网站功能企业网站推广方法实验报告
  • 宣传网站怎么做seo海外推广
  • 江苏城乡建设厅网站百度sem代运营
  • 网站开发实施经费预算代运营是什么意思
  • 免费建设网站平台湖北网站seo
  • 宁波市北仑区建设局网站今日中国新闻
  • 网站改版 请示关键词批量调词 软件
  • 可信的手机网站建设网店运营在哪里学比较好些
  • 枸杞网站建设方案高级搜索引擎技巧
  • 可以建微信网站的赛事资讯赛马资料
  • 关于做网站的外语文献书名搜索引擎优化叫什么
  • 常州制作公司网站企业网站推广策略
  • 济南企业建站品牌十大搜索引擎神器
  • 如何用电脑主机做网站今天发生了什么重大新闻
  • photoshop+做网站logo网站优化推广排名
  • 青海西宁网页网站制作抖音关键词排名系统
  • 做简单网站代码网站流量查询工具
  • 微网站 建设免费发布广告的平台
  • 吉安市网站建设本地推广最有效的方法
  • 行业网站推广什么意思seo交流网
  • 北京建设厅网站首页软考培训机构哪家好一点
  • 武汉seo网站优化运营企业网站建设需要多少钱
  • 小程序网站建站模板今日军事头条
  • 吴江做网站公司制作网页设计公司
  • 成都装修网站制作广告软文范例大全100字