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

站长工具是什么小程序开发教程视频

站长工具是什么,小程序开发教程视频,河南省郑州市金水区,上海莱布拉网站建设前言 大家好吖,欢迎来到 YY 滴C系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! 目录 一.AVL树的概念二.AVL树节点的定义(代码…

前言

大家好吖,欢迎来到 YY 滴C++系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁
主要内容含:
在这里插入图片描述

欢迎订阅 YY滴C++专栏!更多干货持续更新!以下是传送门!

目录

  • 一.AVL树的概念
  • 二.AVL树节点的定义(代码演示)
  • 三.Avl树的基本操作:插入
  • 四.AVL树的核心操作:旋转
    • 【1】新节点插入较高右子树的右侧---右右:左单旋
    • 【2】新节点插入较高左子树的左侧—左左:右单旋
    • 【3】新节点插入较高左子树的右侧---左右:先左单旋再右单旋
    • 【4】新节点插入较高右子树的左侧---右左:先右单旋再左单旋
  • 五.AVL树的验证
      • 1. 验证其为二叉搜索树
      • 2. 验证其为平衡树
  • 六.AVL树的性能&引入红黑树
  • 七.AVL树的完整代码

一.AVL树的概念

  • 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证 每个结点的左右子树高度之差的绝对值不超过1 (需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
  • 平衡因子是-1,左比右高1;平衡因子是1,右比左高1;平衡因子是0,左右一样高
  • 一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
    1. 它的左右子树都是AVL树
    2. 左右子树高度之差(简称平衡因子)的绝对值不超过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树节点的定义(代码演示)

  • 除了基本的左右孩子节点与数据外,还需要引入平衡因子
  • 由于平衡因子取决于左右子树相对高度,所以节点本身 要能够返回父亲节点 ——> 要设置指向父亲节点的指针
  • 注意AVL树节点是三叉链
template<class T>
struct AVLTreeNode
{AVLTreeNode(const T& data): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _bf(0){}AVLTreeNode<T>* _pLeft;   // 该节点的左孩子AVLTreeNode<T>* _pRight;  // 该节点的右孩子AVLTreeNode<T>* _pParent; // 该节点的父亲节点T _data;int _bf;                  // 该节点的平衡因子
};

三.Avl树的基本操作:插入

  • AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么 AVL树的插入过程可以分为两步:
    1. 按照二叉搜索树的方式插入新节点
    2. 调整节点的平衡因子
  • AVL树的插入过程:
  • 与二叉搜索树同理,二叉搜索树博客传送门:https://blog.csdn.net/YYDsis/article/details/134374001?spm=1001.2014.3001.5501
  • 平衡因子的变化步骤:
  1. 新增在左,parent平衡因子减减
  2. 新增在右,parent平衡因子加加
  3. 平衡因子==0,高度不变,直接break
  4. 平衡因子==1/-1,高度改变-> 会影响祖先 -> 需要继续沿着到根节点root的路径向上更新
  5. 平衡因子==2/-2,高度改变& 树不再平衡 ->会影响祖先->需要对parent所在子树进行 旋转 操作,让其平衡 (旋转部分放在part4中详解)
  6. 向上更新,直到根节点(根节点parent==0)
template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}//1. 按照二叉搜索树的方式插入新节点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 (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//2. 调整节点的平衡因子while (parent)//向上更新,直到根节点(根节点parent==0){if (cur == parent->_left)// 1.新增在左,parent平衡因子减减{parent->_bf--;}else // if (cur == parent->_right){parent->_bf++;//2.新增在右,parent平衡因子加加}if (parent->_bf == 0)//3.平衡因子==0,高度不变,直接break{// 更新结束break;}//4.平衡因子==1/-1,高度改变-> 会影响祖先 -> 需要继续沿着到根节点root的路径向上更新else if (parent->_bf == 1 || parent->_bf == -1){// 继续往上更新cur = parent;parent = parent->_parent;}//平衡因子==2/-2,高度改变& 树不再平衡 ->会影响祖先->//需要对parent所在子树进行 旋转 操作,让其平衡else if (parent->_bf == 2 || parent->_bf == -2){// 子树不平衡了,需要旋转     (旋转部分为何这么设计放在part4中详解)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;}else{assert(false);}}return true;}

四.AVL树的核心操作:旋转

  • 根据part3中avl树的基本操作"插入",以下情况会出现旋转
  • 平衡因子==2/-2,高度改变& 树不再平衡 ->会影响祖先->需要对parent所在子树进行 旋转 操作,让其平衡 (旋转部分放在part4中详解)
  • 所以一共有四种情况分别如下图所示:
  • 旋转要注意以下两点:
    1. 保持这颗树还是搜索树
    2. 变成平衡树&降低其高度

【1】新节点插入较高右子树的右侧—右右:左单旋

  • 分析:
  • 如下图所示,新节点插入较高右子树的右侧时候,整体会发生“向左的单旋”

在这里插入图片描述

  • 核心操作:
    cur->_right = parent;
    parent->_parent = cur;
  • 代码展示:
void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;parent->_right = curleft;if (curleft){curleft->_parent = parent;}cur->_left = parent;Node* ppnode = parent->_parent;parent->_parent = cur;if (parent == _root){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}parent->_bf = cur->_bf = 0;}

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

【3】新节点插入较高左子树的右侧—左右:先左单旋再右单旋

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

五.AVL树的验证

1. 验证其为二叉搜索树

  • 如果其通过 中序遍历 可得到一个有序的序列,就说明为二叉搜索树

2. 验证其为平衡树

  • 每个节点子树高度差的绝对值不超过1(注意节点中如果没有平衡因子)
  • 节点的平衡因子是否计算正确

六.AVL树的性能&引入红黑树

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

  • 红黑树博客传送门:

七.AVL树的完整代码

#pragma once#include<iostream>
#include<assert.h>
using namespace std;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
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const 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 (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;// ... 控制平衡// 更新平衡因子while (parent){if (cur == parent->_left){parent->_bf--;}else // if (cur == parent->_right){parent->_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){// 子树不平衡了,需要旋转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;}else{assert(false);}}return true;}void RotateL(Node* parent){++_rotateCount;Node* cur = parent->_right;Node* curleft = cur->_left;parent->_right = curleft;if (curleft){curleft->_parent = parent;}cur->_left = parent;Node* ppnode = parent->_parent;parent->_parent = cur;if (parent == _root){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}parent->_bf = cur->_bf = 0;}void RotateR(Node* parent){++_rotateCount;Node* cur = parent->_left;Node* curright = cur->_right;parent->_left = curright;if (curright)curright->_parent = parent;Node* ppnode = parent->_parent;cur->_right = parent;parent->_parent = cur;if (ppnode == nullptr){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}parent->_bf = cur->_bf = 0;}void RotateRL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;int bf = curleft->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){cur->_bf = 0;curleft->_bf = 0;parent->_bf = 0;}else if (bf == 1){cur->_bf = 0;curleft->_bf = 0;parent->_bf = -1;}else if (bf == -1){cur->_bf = 1;curleft->_bf = 0;parent->_bf = 0;}else{assert(false);}}void RotateLR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;int bf = curright->_bf;RotateL(parent->_left);RotateR(parent);if (bf == 0){parent->_bf = 0;cur->_bf = 0;curright->_bf = 0;}else if (bf == -1){parent->_bf = 1;cur->_bf = 0;curright->_bf = 0;}else if (bf == 1){parent->_bf = 0;cur->_bf = -1;curright->_bf = 0;}}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);}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:Node* _root = nullptr;public:int _rotateCount = 0;
};
http://www.15wanjia.com/news/192892.html

相关文章:

  • 中国太平保险集团官方网站现在哪些网站做外贸的好做
  • 网站搭建的流程是什么怎么查一个公司的网址
  • 网站建设公司网电子商务网店设计
  • 有没有转门做乐器演奏的网站传媒wordpress博客
  • 网站建设的客户在哪里双辽做网站
  • 网站建设设计简介国际消息新闻
  • 手机端网站建设要点网页详情页设计
  • 做网站对程序员说那些需求直接进入网址的浏览器
  • 一鸣东莞网站建设公司如何处理网站死链
  • 如何创建游戏网站德尔普网站建设
  • 国内 上市网站建设公司网站风格类型有哪些
  • 门户网站做商城的财税营销型网站
  • 南京500元做网站广东微信网站制作报价
  • 各大网站投稿邮箱山海关城乡建设局网站
  • 机械网站建设比较好的app开发工具哪个好
  • 同一网站相同form id网站制作可以
  • 定西市小企业网站建设做网站标语
  • 南昌网站seo多少钱江西网站建设公司电话
  • 网站建设与管理维护书籍wordpress html5支持
  • 网站返回503的含义是wordpress 模板破解版
  • 设计师网站十大网站推荐经营范围 网站建设
  • 网站开发技术最新技术p2p 金融网站开发
  • 网站设置密码进入济南建站哪家好
  • 自己做视频的网站吗php图书管理系统网站开发
  • 无锡企业网站seowordpress访问插件
  • 企业网站建设一般要素确山专业网站建设
  • 网站设计分析怎么写百度应用商店app下载安装
  • 康定网站建设工作室wordpress微信付款后查看
  • 企业商城建站wordpress商城 中文站
  • 手机免费建设网站专做零食的网站