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

陕西省政府网站官网站长工具国色天香

陕西省政府网站官网,站长工具国色天香,网站美工做专题尺寸多少,影院网站怎么做一、二叉搜索树(Binary Search Tree, BST) 基本性质 对于树中的每个节点,其左子树中的所有节点值均小于该节点值。其右子树中的所有节点值均大于该节点值。左右子树也分别是二叉搜索树。 极端场景 在极端情况下,如插入节点顺序…

一、二叉搜索树(Binary Search Tree, BST)

基本性质

  1. 对于树中的每个节点,其左子树中的所有节点值均小于该节点值。
  2. 其右子树中的所有节点值均大于该节点值。
  3. 左右子树也分别是二叉搜索树。

极端场景

在极端情况下,如插入节点顺序为升序或降序时,二叉搜索树会退化为链表结构。例如,依次插入 1, 2, 3, 4, 5,此时树的形状为一条从根节点开始不断向右延伸的链。这种退化导致树的高度变为 O (n)(n 为节点数),原本二叉搜索树查找、插入、删除操作平均时间复杂度为 O (log n),此时会退化为 O (n),效率大幅降低。

二、AVL 树(Adelson-Velsky and Landis Tree)

定义与特点

AVL 树是一种自平衡的二叉搜索树。它在向二叉搜索树中插入新节点时,通过特定的旋转操作,保证每个节点的左右子树高度之差的绝对值不超过 1。这使得 AVL 树在动态插入和删除节点过程中,始终保持较为平衡的状态,从而保证基本操作的时间复杂度稳定在 O (log n)。

平衡因子(Balance Factor)

  1. 定义:平衡因子 = 右子树高度 - 左子树高度。
  2. AVL 树的平衡条件:对于 AVL 树中的每一个节点,其平衡因子的绝对值不超过 1。即,| 右子树高度 - 左子树高度 | ≤ 1。当插入或删除节点导致某个节点的平衡因子绝对值大于 1 时,AVL 树会进行相应的旋转操作(左单旋、右单旋、双旋(先左旋后右旋和先右旋后左旋))来重新平衡树结构,确保树始终满足 AVL 树的性质。

 三、AVL 树 的实现

设计结构

1.节点结构

template<class K, class V>
class AVLTreeNode {
public:pair<K, V> _kv;              // 键值对AVLTreeNode<K, V>* _left;     // 左子节点AVLTreeNode<K, V>* _right;    // 右子节点AVLTreeNode<K, V>* _parent;   // 父节点(关键,用于回溯调整平衡)int _bf;                      // 平衡因子(右子树高度 - 左子树高度)AVLTreeNode(const pair<K,V>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0){}
};

2.树结构

template<class K, class V>
class AVLTree {typedef AVLTreeNode<K, V> Node;
public://增删改查操作//......
private:Node* _root = nullptr;  // 根节点
};

操作函数

插入

1.查找插入位置

  • 若树为空,直接创建根节点。
  • 否则,从根节点开始遍历查找:

    bool insert(const pair<K, V>& kv) {if (_root == nullptr) {      // 空树直接插入_root = new Node(kv);return true;}Node* cur = _root, *parent = nullptr;while (cur) {                // 向下搜索插入位置parent = cur;if (kv.first < cur->_kv.first) cur = cur->_left;else if (kv.first > cur->_kv.first) cur = cur->_right;else return false;       // 重复键不允许插入}

2.插入新节点

  • 创建新节点 cur,根据键值大小链接到父节点的左或右。

        cur = new Node(kv);cur->_parent = parent;       // 绑定父节点if (kv.first < parent->_kv.first) parent->_left = cur;     // 插入到左子树else parent->_right = cur;    // 插入到右子树
  • 设置 cur->_parent = parent(关键,后续调整依赖父指针)。

3.更新平衡因子

  • 从插入点的父节点向上回溯,调整每个祖先节点的平衡因子:

    • 插入在左子树:parent->_bf--

    • 插入在右子树:parent->_bf++

  • 根据平衡因子决定是否继续调整或旋转:

    • _bf == 0:停止调整(子树高度未变)。

    • |_bf| == 1:继续向上调整。

    • |_bf| == 2:触发旋转(需判断旋转类型)。

    while (parent) {             // 从父节点向上回溯调整if (cur == parent->_left) parent->_bf--;else parent->_bf++;if (parent->_bf == 0) break;     // 高度不变,无需调整else if (abs(parent->_bf) == 1) { // 高度变化,继续向上cur = parent;parent = parent->_parent;}else if (abs(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) rotateRL(parent);       //右-左旋else if (parent->_bf == -2 && cur->_bf == 1) rotateLR(parent);       //左-右旋break;}}return true;
}

左单旋(rotateL

  • 确定关键节点

    • parent:失衡节点(_bf == 2)。

    • curparent的右子节点(_bf == 1)。

    • curleftcur的左子节点。

    • grandParentparent的父节点。

  • 调整指针关系

1.处理curleft

  • parent->_right = curleft:将parent的右子指向curleft
  • curleft存在:设置curleft->_parent = parent

2.建立curparent关系

  • cur->_left = parentcur的左子指向原父节点。
  • parent->_parent = cur:原父节点的父指针指向cur

3.链接到原树

  • cur->_parent = grandParentcur的父指针指向原祖父。
  • grandParent为空:更新根节点为cur
  • 否则:根据parent在原树的位置,将grandParent的左/右子指向cur

  • 更新平衡因子

    • parent->_bf = 0

    • cur->_bf = 0

完整代码

void rotateL(Node* parent) {Node* grandParent = parent->_parent;Node* cur = parent->_right, * curleft = cur->_left;parent->_right = curleft;if (curleft) {curleft->_parent = parent;}cur->_left = parent;parent->_parent = cur;cur->_parent = grandParent;if (grandParent == nullptr) {_root = cur;}else {if (parent == grandParent->_left) {grandParent->_left = cur;}else {grandParent->_right = cur;}}parent->_bf = cur->_bf = 0;
}

右单旋 (rotateR) 

  • 参考图:
    • 确定关键节点,调节指针关系:
    • 链接到原树 :
  • 复现代码:
    void rotateR(Node* parent) {Node* grandParent = parent->_parent;Node* cur = parent->_left, * curright = cur->_right;parent->_left = curright;if (curright) {curright->_parent = parent;}cur->_right = parent;parent->_parent = cur;if (grandParent == nullptr) {_root = cur;cur->_parent = nullptr;}else {if (grandParent->_left == parent) {grandParent->_left = cur;}else {grandParent->_right = cur;}cur->_parent = grandParent;}parent->_bf = cur->_bf = 0;
    }

左-右双旋 (rotateLR)

适用场景
父节点平衡因子为 -2,左子节点平衡因子为 1(左子树的右子树过高)。

步骤

1.定位关键节点

  • parent:失衡节点(平衡因子 -2)。

  • curparent 的左子节点(平衡因子 1)。

  • currightcur 的右子节点(需记录其原始平衡因子 tmpbf)。

2.执行双旋

  • 先左旋:对 cur 调用左单旋(rotateL),使 curright 成为新的左子树根。

  • 再右旋:对 parent 调用右单旋(rotateR),使 curright 成为新的根节点。

3.调整平衡因子

 

  • tmpbf == 1

    • parent->_bf = 0cur->_bf = -1(左子树高度减少)。

    • curright->_bf = 0

  • tmpbf == -1

    • parent->_bf = 1(右子树高度增加)。

    • cur->_bf = 0curright->_bf = 0

  • tmpbf == 0:所有相关节点平衡因子置 0

完整代码

void rotateLR(Node* parent) {Node* cur = parent->_left, * curright = cur->_right;int tmpbf = curright->_bf;rotateL(parent->_left);rotateR(parent);if (tmpbf == -1) {cur->_bf = 0;curright->_bf = 0;parent->_bf = 1;}else if (tmpbf == 1) {parent->_bf = 0;cur->_bf = -1;curright->_bf = 0;}else if (tmpbf == 0) {parent->_bf = cur->_bf = curright->_bf = 0;}else {assert(false);}
}

 

右-左双旋(rotateRL) 

适用场景
父节点平衡因子为 2,右子节点平衡因子为 -1(右子树的左子树过高)。

步骤

1.定位关键节点

  • parent:失衡节点(平衡因子 2)。

  • curparent 的右子节点(平衡因子 -1)。

  • curleftcur 的左子节点(需记录其原始平衡因子 tmpbf)。

2.执行双旋

  • 先右旋:对 cur 调用右单旋(rotateR),使 curleft 成为新的右子树根。

  • 再左旋:对 parent 调用左单旋(rotateL),使 curleft 成为新的根节点。

3.调整平衡因子

  • tmpbf == -1

    • parent->_bf = 0cur->_bf = 1(右子树高度增加)。

    • curleft->_bf = 0

  • tmpbf == 1

    • parent->_bf = -1(左子树高度减少)。

    • cur->_bf = 0curleft->_bf = 0

  • tmpbf == 0:所有相关节点平衡因子置 0

补充:在 AVL 树的双旋转操作(如rotateRLrotateLR)完成后需要调整平衡因子的原因?

在左单旋(rotateL)和右单旋(rotateR)操作中,旋转完成后直接将相关节点的平衡因子置为 0。这是因为单旋转操作在特定的失衡情况下进行,能够一步将树调整为平衡状态,旋转后相关节点的左右子树高度差重新达到平衡,所以可以简单地将平衡因子置为 0。

双旋转(rotateRL 和 rotateLR)是由两次单旋转组合而成,情况更为复杂。双旋转操作会改变多个节点的左右子树结构,旋转后不同节点的左右子树高度变化不能简单地通过将平衡因子置为 0 来处理,需要根据旋转前子节点的平衡因子情况来具体调整。(具体如何调整合一参考 rotateRL 和 rotateLR  的图解和实现)

 

http://www.dtcms.com/wzjs/107679.html

相关文章:

  • 网站站点结构图怎么做东莞最新消息 今天
  • 厦门网站的建设网络优化师是什么工作
  • 如何再国外网站做折扣优化推广网站seo
  • 商城网站是怎么做的销售课程视频免费
  • 忻州网站建设公司磁力狗在线引擎
  • 网站滚动字幕代码优化营商环境 助推高质量发展
  • 足彩网站建设上海seo优化
  • 做网站的大骗子流量主广告点击自助平台
  • 男的做那个视频网站自己建网站需要钱吗
  • 哪些公司做企业网站百度搜索引擎推广怎么弄
  • wordpress 老萨seo优化的基本流程
  • 兰州网站建设怎么选我要发布信息
  • 经典网站设计案例代运营公司前十名
  • 部门网站建设的目的和意义seo网站推广技术
  • 天元建设集团有限公司 田新鹏seo优化思路
  • 网站直播间 是怎么做的百度竞价排名模式
  • 如何打开网站的源代码制作一个网站的基本步骤
  • 网站站点建立软文写作是什么
  • 大专ui设计师工资一般多少合肥全网优化
  • win7系统可以做网站吗网站seo规划
  • 建网站需要多少钱和什么条件才能建提高网站流量的软文案例
  • 有没有做公章的网站东莞百度seo推广公司
  • 网站的推广方式组合南通百度网站快速优化
  • 企业官方网站制作推广软件最好的免费推广平台
  • 外贸网站建设步骤新东方雅思培训机构官网
  • 网站开发公司模板淘宝关键词优化怎么弄
  • 好项目找投资人免费平台宁波seo深度优化平台有哪些
  • 电商网站怎样做优化才最合理网络营销的平台有哪些
  • 做高端网站的网络公司青岛网站
  • b2b网站的分类推广图片制作