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

企业网站建设代理商搜索引擎市场份额2023

企业网站建设代理商,搜索引擎市场份额2023,开发公众号,如何百度到自己的网站AVL树 1.AVL树的概念2.平衡因子3.节点的定义4.插入操作5.旋转操作#xff08;重点#xff09;5.1左单旋5.2右单旋5.3左右双旋5.4右左双旋 6.一些简单的测试接口7.完整代码 1.AVL树的概念 普通二叉搜索树#xff1a;二叉搜索树 二叉搜索树虽可以缩短查找的效率#xff0c;但… AVL树 1.AVL树的概念2.平衡因子3.节点的定义4.插入操作5.旋转操作重点5.1左单旋5.2右单旋5.3左右双旋5.4右左双旋 6.一些简单的测试接口7.完整代码 1.AVL树的概念 普通二叉搜索树二叉搜索树 二叉搜索树虽可以缩短查找的效率但如果数据有序或接近有序普通的二叉搜索树将退化为单支树查找元素相当于在顺序表中搜索元素效率低下。因此两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法(AVL树是以这两位的名字命名的)当向二叉搜索树中插入新结点后如果能保证每个结点的左右子树高度之差的绝对值不超过1超过了需要对树中的结点进行调整(旋转)即可降低树的高度从而减少平均搜索长度。 AVL树也是二叉搜索树但有以下特点 它的左右子树都是AVL树左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)如果一棵二叉搜索树是高度平衡的它就是AVL树。如果它有n个结点其高度可保持在 O ( l o g 2 n ) O(log_2 n) O(log2​n)搜索时间复杂度O( l o g 2 n log_2 n log2​n)。 2.平衡因子 AVL树的实现有很多种本文引入平衡因子来维持高度稳定。 本文平衡因子的定义右子树高度 - 左子树的高度。 依据每个节点的平衡因子我们可以判断树的情况 平衡因子在(-1, 0, 1)当前节点所在子树是稳定的。平衡因子为2或-2当前节点所在子树是不稳定的。 插入节点后平衡因子的更新 插入节点在右子树平衡因子加一。插入节点在左子树平衡因子减一。 插入节点后平衡因子的不同情况重点 当前节点所在子树平衡因子为0子树高度不变不需要更新原来一边高一边低新插入在低一方变成完全平衡。当前节点所在子树平衡因子为1或-1子树高度变化需要向上更新。原来完全平衡现在一边高子树整体高度加1会影响到祖先的平衡故需要向上更新看祖先所在子树是否平衡当前节点所在子树平衡因子为2或-2子树高度变化且不平衡无需向上更新对当前子树进行旋转操作。当前子树已不平衡向上更新没有意义旋转操作是AVL树的核心可以降低当前子树的高度且不影响上面的树结构 3.节点的定义 节点除了需要增加一个平衡因子还需要增加一个父亲指针方便我们进行平衡因子的向上更新和旋转操作。 templateclass K, class V struct ALVTreeNode {ALVTreeNodeK, V* _left;ALVTreeNodeK, V* _right;ALVTreeNodeK, V* _parent;pairK, V _kv; //存储键值对int _bf; //平衡因子ALVTreeNode(const pairK, V kv):_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0),_kv(kv){} };4.插入操作 PS因为多加了一个父亲指针所以插入时要注意更新父亲指针平衡因子更新按前面的分析来还是比较简单的旋转操作后面单独讲。 bool Insert(const pairK, V kv) {if (_root nullptr) //一开始为空树直接插入即可{_root new Node(kv);return true;}//找插入位置加插入Node* cur _root; //记录插入位置Node* parent nullptr; //待插入位置的父亲while (cur){if (kv.first cur-_kv.first) //待插入节点在右子树{parent cur;cur cur-_right;}else if (kv.first cur-_kv.first) //待插入节点在左子树{parent cur;cur cur-_left;}else //待插入节点已存在{return false;}}cur new Node(kv);if (kv.first parent-_kv.first) //插入在父亲的右边{parent-_right cur;}else //插入在父亲的左边{parent-_left cur;}cur-_parent parent; //注意更新父亲指针//调整平衡因子while (parent) //是有可能调整到根部的{if (cur parent-_right) //如果新插入的在右子树{parent-_bf;}else if (cur parent-_left) //如果新插入的在左子树{parent-_bf--;}if (parent-_bf 0) //插入后高度不变{break;}else if (parent-_bf 1 || parent-_bf -1) //插入后高度变化但当前子树依然平衡需要向上更新{parent parent-_parent;cur cur-_parent;}else if (parent-_bf 2 || parent-_bf -2) //插入后高度变化并且当前子树已经不平衡,旋转{//旋转操作先省略break;}else //存在大于2小于-2的情况树原来就不平衡应该报错{assert(false);}}return true; }5.旋转操作重点 5.1左单旋 主体思想 平衡因子的调整 代码加细节处理 void RotateL(Node* parent) //左单旋,rotate-旋转 {Node* SubR parent-_right;Node* SubRL SubR-_left; //这个有可能为空Node* ppnode parent-_parent; //原来父亲的父亲parent-_right SubRL;if(SubRL) SubRL-_parent parent;SubR-_left parent;parent-_parent SubR;if (ppnode nullptr) //旋转的是整颗树{_root SubR;SubR-_parent nullptr;}else //旋转的是部分{if (ppnode-_left parent) //是左子树{ppnode-_left SubR;}else //是右子树{ppnode-_right SubR;}SubR-_parent ppnode;}//最后更新平衡因子parent-_bf SubR-_bf 0; }5.2右单旋 PS右单旋和左单旋类似细节处理也差不多这里只讲主体思路。 主体思路 平衡因子的调整 代码 void RotateR(Node* parent) //右单旋细节处理和左单旋差不多 {Node* SubL parent-_left;Node* SubLR SubL-_right; //这个有可能为空Node* ppnode parent-_parent;parent-_left SubLR;if(SubLR) SubLR-_parent parent;SubL-_right parent;parent-_parent SubL;if (ppnode nullptr) //旋转的是整颗树{_root SubL;SubL-_parent nullptr;}else //旋转部分{if (ppnode-_left parent) //是左子树{ppnode-_left SubL;}else //右子树{ppnode-_right SubL;}SubL-_parent ppnode;}//最后更新平衡因子parent-_bf SubL-_bf 0; }5.3左右双旋 PS双旋其实就是两次单旋(复用即可)有前面的基础很好理解重点在于旋转后平衡因子的更新。 旋转思路 平衡因子的调整 想知道平衡因子调整是那种情况我们需要在旋转前记录SubRL的平衡因子bf bf为0是第一种情况。bf为1是第二种情况。bf为-1是第三种情况。 代码 void RotateLR(Node* parent) //左右双旋 {Node* SubL parent-_left;Node* SubLR SubL-_right;int bf SubLR-_bf;RotateL(SubL);RotateR(parent);if (bf 1) //插入的是右边{SubLR-_bf 0;SubL-_bf -1;parent-_bf 0;}else if (bf -1) //插入的是左边{SubLR-_bf 0;SubL-_bf 0;parent-_bf 1;}else if (bf 0) //刚好原来parent的左边就两个节点{SubLR-_bf SubL-_bf parent-_bf 0;}else //原来就不是平衡树出现问题{assert(false);} }5.4右左双旋 PS右左双旋和左右双旋思路是差不多的重点还是在旋转后平衡因子的更新。 旋转思路 平衡因子的调整 和前面一样旋转前确认SubRL的平衡因子bf即可。 代码 void RotateRL(Node* parent) //右左双旋 {Node* SubR parent-_right;Node* SubRL SubR-_left;int bf SubRL-_bf;RotateR(SubR);RotateL(parent);if (bf 1) //插入的是右边{SubRL-_bf 0;SubR-_bf 0;parent-_bf -1;}else if (bf -1) //插入的是左边{SubRL-_bf 0;parent-_bf 0;SubR-_bf 1;}else if (bf 0) //原来parent的右边就两个节点{SubRL-_bf SubR-_bf parent-_bf 0;}else //原来就有问题{assert(false);} }6.一些简单的测试接口 int Height() {return _Height(_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() {return IsBalance(_root); }//看当前树是不是平衡树 //1看每个子树是否满足左右子树高度差不超过一 //2看平衡因子和所求的左右子树高度差是否一致 bool IsBalance(Node* root) {if (root nullptr)return true;int leftHight _Height(root-_left);int rightHight _Height(root-_right);if (rightHight - leftHight ! root-_bf){cout 平衡因子异常: root-_kv.first - root-_bf endl;return false;}return abs(rightHight - leftHight) 2 IsBalance(root-_left) IsBalance(root-_right); }7.完整代码 #pragma once #include iostream #include assert.h #include utility using namespace std;templateclass K, class V struct ALVTreeNode {ALVTreeNodeK, V* _left;ALVTreeNodeK, V* _right;ALVTreeNodeK, V* _parent;pairK, V _kv; //存储键值对int _bf;ALVTreeNode(const pairK, V kv):_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0),_kv(kv){} };templateclass K, class V class AVLTree { public:typedef ALVTreeNodeK, V Node;bool Insert(const pairK, V kv){if (_root nullptr) //一开始为空树直接插入即可{_root new Node(kv);return true;}Node* cur _root; //记录插入位置Node* parent nullptr; //待插入位置的父亲while (cur){if (kv.first cur-_kv.first) //待插入节点在右子树{parent cur;cur cur-_right;}else if (kv.first cur-_kv.first) //待插入节点在左子树{parent cur;cur cur-_left;}else //待插入节点已存在{return false;}}cur new Node(kv);if (kv.first parent-_kv.first) //插入在父亲的右边{parent-_right cur;}else //插入在父亲的左边{parent-_left cur;}cur-_parent parent;//调整平衡因子while (parent) //是有可能调整到根部的{if (cur parent-_right) //如果新插入的是右子树{parent-_bf;}else if (cur parent-_left) //如果新插入的是左子树{parent-_bf--;}if (parent-_bf 0) //插入后高度不变{break;}else if (parent-_bf 1 || parent-_bf -1) //插入后高度变化但当前子树依然平衡需要向上更新{parent parent-_parent;cur cur-_parent;}else if (parent-_bf 2 || parent-_bf -2) //插入后高度变化并且当前子树已经不平衡,旋转{//旋转if (parent-_bf 2 cur-_bf 1) //左单旋{RotateL(parent);}else if (parent-_bf -2 cur-_bf -1) //右单旋{RotateR(parent);}else if (parent-_bf -2 cur-_bf 1) //左子树的右边高左右双旋{RotateLR(parent);}else if (parent-_bf 2 cur-_bf -1) //右子树的左边高右左双旋{RotateRL(parent);}else //原来就不是平衡树{assert(false);}break;}else //树原来就不平衡应该报错{assert(false);}}return true;}////int Height(){return _Height(_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(){return IsBalance(_root);}//看当前树是不是平衡树//1看每个子树是否满足左右子树高度差不超过一//2看平衡因子和所求的左右子树高度差是否一致bool IsBalance(Node* root){if (root nullptr)return true;int leftHight _Height(root-_left);int rightHight _Height(root-_right);if (rightHight - leftHight ! root-_bf){cout 平衡因子异常: root-_kv.first - root-_bf endl;return false;}return abs(rightHight - leftHight) 2 IsBalance(root-_left) IsBalance(root-_right);}private:void RotateL(Node* parent) //左单旋,rotate-旋转{Node* SubR parent-_right;Node* SubRL SubR-_left; //这个有可能为空Node* ppnode parent-_parent; //原来父亲的父亲parent-_right SubRL;if(SubRL) SubRL-_parent parent;SubR-_left parent;parent-_parent SubR;if (ppnode nullptr) //旋转的是整颗树{_root SubR;SubR-_parent nullptr;}else //旋转的是部分{if (ppnode-_left parent) //是左子树{ppnode-_left SubR;}else //是右子树{ppnode-_right SubR;}SubR-_parent ppnode;}//最后更新平衡因子parent-_bf SubR-_bf 0;}void RotateR(Node* parent) //右单旋细节处理和左单旋差不多{Node* SubL parent-_left;Node* SubLR SubL-_right; //这个有可能为空Node* ppnode parent-_parent;parent-_left SubLR;if(SubLR) SubLR-_parent parent;SubL-_right parent;parent-_parent SubL;if (ppnode nullptr) //旋转的是整颗树{_root SubL;SubL-_parent nullptr;}else //旋转部分{if (ppnode-_left parent) //是左子树{ppnode-_left SubL;}else //右子树{ppnode-_right SubL;}SubL-_parent ppnode;}//最后更新平衡因子parent-_bf SubL-_bf 0;}void RotateLR(Node* parent) //左右双旋{Node* SubL parent-_left;Node* SubLR SubL-_right;int bf SubLR-_bf;RotateL(SubL);RotateR(parent);if (bf 1) //插入的是右边{SubLR-_bf 0;SubL-_bf -1;parent-_bf 0;}else if (bf -1) //插入的是左边{SubLR-_bf 0;SubL-_bf 0;parent-_bf 1;}else if (bf 0) //刚好原来parent的左边就两个节点{SubLR-_bf SubL-_bf parent-_bf 0;}else //原来就不是平衡树出现问题{assert(false);}}void RotateRL(Node* parent) //右左双旋{Node* SubR parent-_right;Node* SubRL SubR-_left;int bf SubRL-_bf;RotateR(SubR);RotateL(parent);if (bf 1) //插入的是右边{SubRL-_bf 0;SubR-_bf 0;parent-_bf -1;}else if (bf -1) //插入的是左边{SubRL-_bf 0;parent-_bf 0;SubR-_bf 1;}else if (bf 0) //原来parent的右边就两个节点{SubRL-_bf SubR-_bf parent-_bf 0;}else //原来就有问题{assert(false);}}Node* _root nullptr; };
http://www.zqtcl.cn/news/93571/

相关文章:

  • 建筑行业综合查询平台优化推广联盟
  • 北京管庄网站建设公司开平网站制作
  • 如何做销售直播网站最专业网站建设
  • 太原市住房和城乡建设局的网站首页网络推广服务外包公司
  • 湘icp备 网站建设 农业 湖南稿定设计免费版
  • 公司网站推广方法陕西省住房建设厅官网
  • 网站关键词排名突然没了无锡企业网站建设报价
  • 找做网站的人网站改版 301跳转
  • 网站备案一次就可以了吧营销管理培训课程
  • 怎么做网站背景专做民宿预定的网站
  • wordpress安装谷歌分析代码建网站seo
  • 百度外卖网站建设与维护方法建设 银行网网站
  • 小程序开发定制开发上海优化价格
  • 来宾住房和城乡建设局网站做外贸推广要做哪些平台
  • 无锡建设网站制作wordpress 知乎
  • 动漫网站源码免费怎么怎么做网站
  • 和两个黑人同时做网站中工互联网站建设
  • windows10PHP 网站建设app应用分发平台开发
  • 中唯建设工程有限公司网站做网站页面对PS切图
  • 个人网页制作成品欣赏seo网站沙盒期
  • 亚马逊站外推广网站怎么做制作营销网站模板免费下载
  • 加拿大网站后缀设计师互联网
  • 做物流的网站有哪些内容共同建设网站心得
  • 主题资源网站建设什么网站做污水处理药剂的好
  • 河北建设厅网站修改密码在哪58同城宿迁二手房
  • 淘宝联盟的购物网站怎么做免费网站模板素材
  • 淄博市网站云平台长沙seo 优化选智投未来no1
  • 手机网站导航模板wordpress子域名设置
  • 济南市网站推广公司甘肃网站建设方案优化
  • 网站排名西安工商所什么网站可做年报