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

网站显示正在建设中泰安网红打卡地

网站显示正在建设中,泰安网红打卡地,中小型企业网站建设,国外网站需要备案吗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.yutouwan.com/news/465189/

相关文章:

  • 网站seo技术能不能赚钱婚纱摄影影楼
  • ui网站界面设计模板手机网站的模板下载软件
  • 网站开发和前端是一样吗wordpress怎样加快访问
  • 快速做网站费用莆田市秀屿区建设局网站
  • 湛江网站网站建设响应式网站是什么
  • rust做网站南京自助网站推广建站
  • 编辑网站的软件手机软件深圳网站优化课程哪里学
  • django怎么做网站wordpress在线课程主题
  • 企业网站建设admin鸣蝉智能建站
  • 小蘑菇网站开发做网站用什么技术好
  • 网站开发工程师月薪平均莱芜雪野湖附近酒店
  • 鄱阳县精准扶贫旅游网站建设目的咖啡网站设计建设
  • 长页网站莱芜网站建设sikesoft
  • 接入备案和增加网站网页制作交城旅游景点
  • 上海网站建设 s江西专业南昌网站建设
  • 网站建设沈阳多语言做网站
  • 制作一个教育网站深圳做网站联雅
  • 嘉兴网站制作套餐wordpress加载优化
  • 企业网站建设需求分析注册网站费用
  • 徐州市中宇建设工程有限公司网站网站开发属于软件设计嘛
  • django网站开发教程合同范本的网站
  • SEO案例网站建设公司小程序公司排名前十
  • 网站开发的缓存技术专门做进口产品的网站6
  • 建设网站考证今天重大新闻乌克兰
  • 免费设计商标的网站万户做网站怎么样
  • 介绍做茶工艺的网站休闲农庄展示网站
  • 东莞做网站排名优化推广php网站微信登录怎么做
  • 苏州专业高端网站建设公司做网站标题代码
  • 做网站属于什么行业郑州哪家公司做网站
  • 给设计网站做图会字体侵权吗济宁网站建设吊装