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

在哪里可以做公司网站重庆电子商务seo

在哪里可以做公司网站,重庆电子商务seo,福建省漳州市建设局网站,手机网站功能目录 一.AVL树的性质 二.AVL树节点的定义 三.AVL树插入操作 四.AVL树的旋转操作 4.1左单旋:新节点插入较高右子树的右侧 4.2右单旋:新节点插入较高左子树的左侧 4.3左右双旋:新节点插入较高左子树的右侧 4.4右左双旋 :新节…

目录

一.AVL树的性质

二.AVL树节点的定义

三.AVL树插入操作 

 四.AVL树的旋转操作

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

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

4.3左右双旋:新节点插入较高左子树的右侧

4.4右左双旋 :新节点插入较高右子树的左侧

五.AVL树验证 

六.AVL树的删除

七.AVL树性能


一.AVL树的性质

当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整)

特点

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

注意:如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在 O(log_2 n),搜索时间复杂度O(log_2 n)

 

 

二.AVL树节点的定义

AVL树的左右子树的高度差不能超过1,那么我们如何让快速判断是不是AVL树呢?

我们可以引入平衡因子来解决这个问题。如果右子树比左子树高一层,则此时平衡因子为1;如果左子树比有子树高一层,则此时平衡因子为-1;如果右子树和左子树一样高,则此时平衡因子为0。(这里平衡因子计算是右子树-左子树,当然左子树-右子树也可以)

依据此规则,如果平衡因子为2/-2,则说明平衡被打破。

在调整不平衡的AVL树时,需要频繁访问父亲节点,所以在AVL树节点定义中,除了定义指向左右节点的指针以外,还需要一个指向父亲节点的指针。

AVL树节点定义如下:

template<class T>
struct AVLTreeNode
{AVLTreeNode(const T& data = T()): _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. 调整节点的平衡因子

平衡因子调节:(pCur为新插入节点,pParent为pCur父亲节点)

pCur插入后,pParent的平衡因子一定需要调整,在插入之前,pParent 的平衡因子分为三种情况:-1,0, 1, 分以下两种情况:

  1. 如果pCur插入到pParent的左侧,只需给pParent的平衡因子-1即可  
  2.  如果pCur插入到pParent的右侧,只需给pParent的平衡因子+1即可  

此时:pParent的平衡因子可能有三种情况:0,正负1, 正负2:  

  • 如果pParent的平衡因子为0,说明插入之前pParent的平衡因子为正负1,插入后被调整 成0,此时满足 AVL树的性质,插入成功  
  • 如果pParent的平衡因子为正负1,说明插入前pParent的平衡因子一定为0,插入后被更 新成正负1,此时以pParent为根的树的高度增加,需要继续向上更新  
  • 如果pParent的平衡因子为正负2,则pParent的平衡因子违反平衡树的性质,需要对其进 行旋转处理

至此我们可以对AVL插入操作有了大致框架:

bool Insert(const T& data)
{Node* newnode = new Node(data);if (_pRoot == nullptr){_pRoot = newnode;return true;}Node* pcur = _pRoot;Node* parent = nullptr;while (pcur){parent = pcur;if (data < pcur->_data){pcur = pcur->_pLeft;}else if (data > pcur->_data){pcur = pcur->_pRight;}else{return false;}}if (parent->_data < data){parent->_pRight = newnode;}elseparent->_pLeft = newnode;//从下往上更新平衡因子pcur = newnode;while (parent){if (pcur == parent->_pLeft){parent->_bf--;}else{parent->_bf++;}if (parent->_bf == 0){//...}else if (parent->_bf == 1 || parent->_bf == -1){//...}else if (parent->_bf == 2 || parent->_bf == -2){//...break;//旋转后字数高度不变,不需要向上调整}else{return false;}}return true;
}

 四.AVL树的旋转操作

在插入操作时我们提出有2和-2的特使情况,这时候就需要进行旋转操作。

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

由图可以看出,在a插入一个节点则右边比较高,为了保持平衡我们需要向左旋转。

代码如下:

// 左单旋
void RotateL(Node* parent)
{Node* subr = parent->_pRight;Node* subrl = subr->_pLeft;parent->_pRight = subrl;if (subrl)subrl->_pParent = parent;Node* pparent = parent->_pParent;parent->_pParent = subr;if (parent==_pRoot){_pRoot = subr;subr->_pParent = nullptr;}else{if (pparent->_pLeft == parent){pparent->_pLeft=subr;}else{pparent->_pRight=subr;}subr->_pParent = pparent;}subr->_bf = parent->_bf = 0;
}

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

和左单旋类似,代码如下:

// 右单旋
void RotateR(Node* parent)
{Node* subl = parent->_pLeft;Node* sublr = subl->_pRight;parent->_pLeft = sublr;subl->_pRight = parent;if (sublr){sublr->_pParent = parent;}Node* pparent = parent->_pParent;parent->_pParent = subl;if (_pRoot == parent){_pRoot = subl;subl->_pParent = nullptr;}else{if (pparent->_pLeft == parent){pparent->_pLeft=subl;}else{pparent->_pRight=subl;}subl->_pParent = pparent;}subl->_bf = parent->_bf = 0;
}

4.3左右双旋:新节点插入较高左子树的右侧

分成两种情况:

这两种情况都属于在较高左子树的右侧插入,处理方式都是相同的,唯一的区别在于最后旋转完成后,更新平衡因子时的值不同。

我们对其中一种情况进行分析:

 

可以看到这两种情况中,如果在b下面插入新节点,那么旋转过后30和60的平衡因子更新成0,90的平衡因子更新成1;如果在c下面插入新节点,则是60和90的平衡因子更新成0,30的平衡因子更新成-1

而新节点究竟插入到了b下面还是在c下面,我们可以通过插入节点后60的平衡因子来判断。

 

// 左右双旋
void RotateLR(Node* pParent)
{Node* subl = pParent->_pLeft;Node* sublr = subl->_pRight;int bf = sublr->_bf;RotateL(pParent->_pLeft);RotateR(pParent);if (bf == 0){subl->_bf = sublr->_bf = pParent->_bf = 0;}else if (bf == -1){subl->_bf = sublr->_bf = 0;pParent->_bf = 1;}else if (bf == 1){pParent->_bf =sublr->_bf = 0;subl->_bf = -1;}
}

4.4右左双旋 :新节点插入较高右子树的左侧

// 右左双旋
void RotateRL(Node* pParent)
{Node* subr = pParent->_pRight;Node* subrl = subr->_pLeft;int bf = subrl->_bf;RotateR(pParent->_pRight);RotateL(pParent); if (bf == 0){subr->_bf = subrl->_bf = pParent->_bf = 0;}else if (bf == 1){subrl->_bf =subr->_bf= 0;pParent->_bf = -1;}else if (bf == -1){pParent->_bf = subrl->_bf = 0;subr->_bf = 1;}
}

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

1. pParent的平衡因子为2,说明pParent的右子树高,设pParent的右子树的根为pSubR

  • 当pSubR的平衡因子为1时,执行左单旋
  • 当pSubR的平衡因子为-1时,执行右左双旋

2. pParent的平衡因子为-2,说明pParent的左子树高,设pParent的左子树的根为pSubL

  • 当pSubL的平衡因子为-1是,执行右单旋
  • 当pSubL的平衡因子为1时,执行左右双旋

旋转完成后,原pParent为根的子树个高度降低,已经平衡,不需要再向上更新。  

五.AVL树验证 

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

1. 验证其为二叉搜索树

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

2. 验证其为平衡树

  • 每个节点子树高度差的绝对值不超过1(注意节点中如果没有平衡因子)
  • 节点的平衡因子是否计算正确
// 根据AVL树的概念验证pRoot是否为有效的AVL树
bool _IsAVLTree(Node* pRoot)
{if (pRoot == nullptr){return true;}int leftheight = _Height(pRoot->_pLeft);int rightheight = _Height(pRoot->_pRight);if (rightheight - leftheight !=pRoot->_bf){cout << "平衡因子异常" << endl;return false;}return abs(rightheight - leftheight) <= 1 && _IsAVLTree(pRoot->_pLeft)&& _IsAVLTree(pRoot->_pRight);
}
size_t _Height(Node* pRoot)
{if (pRoot == nullptr){return 0;}size_t lefth=_Height(pRoot->_pLeft);size_t righth = _Height(pRoot->_pRight);return max(lefth, righth)+1;
}

六.AVL树的删除

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

七.AVL树性能

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

完整代码:

#pragma once
#include<iostream>
using namespace std;
template<class T>
struct AVLTreeNode
{AVLTreeNode(const T& data = T()): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _bf(0){}AVLTreeNode<T>* _pLeft;AVLTreeNode<T>* _pRight;AVLTreeNode<T>* _pParent;T _data;int _bf;// 节点的平衡因子
};// AVL: 二叉搜索树 + 平衡因子的限制
template<class T>
class AVLTree
{typedef AVLTreeNode<T> Node;
public:AVLTree(): _pRoot(nullptr){}// 在AVL树中插入值为data的节点bool Insert(const T& data){Node* newnode = new Node(data);if (_pRoot == nullptr){_pRoot = newnode;return true;}Node* pcur = _pRoot;Node* parent = nullptr;while (pcur){parent = pcur;if (data < pcur->_data){pcur = pcur->_pLeft;}else if (data > pcur->_data){pcur = pcur->_pRight;}else{return false;}}if (parent->_data < data){parent->_pRight = newnode;}elseparent->_pLeft = newnode;//从下往上更新平衡因子pcur = newnode;while (parent){if (pcur == parent->_pLeft){parent->_bf--;}else{parent->_bf++;}if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){pcur = parent;parent = pcur->_pParent;}else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == 2 && pcur->_bf == 1){RotateL(parent);}else if (parent->_bf == -2 && pcur->_bf == -1){RotateR(parent);}else if (parent->_bf == -2 && pcur->_bf == 1){RotateLR(parent);}else if (parent->_bf == 2 && pcur->_bf == -1){RotateRL(parent);}break;//旋转后字数高度不变,不需要向上调整}else{return false;}}return true;}// AVL树的验证bool IsAVLTree(){return _IsAVLTree(_pRoot);}void _Inorder(Node* Root){if (Root == nullptr){return ;}_Inorder(Root->_pLeft);cout << Root->_data << " ";_Inorder(Root->_pRight);}void Inorder(){_Inorder(_pRoot);}
private:// 根据AVL树的概念验证pRoot是否为有效的AVL树bool _IsAVLTree(Node* pRoot){if (pRoot == nullptr){return true;}int leftheight = _Height(pRoot->_pLeft);int rightheight = _Height(pRoot->_pRight);if (rightheight - leftheight !=pRoot->_bf){cout << "平衡因子异常" << endl;return false;}return abs(rightheight - leftheight) <= 1 && _IsAVLTree(pRoot->_pLeft)&& _IsAVLTree(pRoot->_pRight);}int _Height(Node* pRoot){if (pRoot == nullptr){return 0;}int lefth=_Height(pRoot->_pLeft);int righth = _Height(pRoot->_pRight);return max(lefth, righth)+1;}// 右单旋void RotateR(Node* parent){Node* subl = parent->_pLeft;Node* sublr = subl->_pRight;parent->_pLeft = sublr;subl->_pRight = parent;if (sublr){sublr->_pParent = parent;}Node* pparent = parent->_pParent;parent->_pParent = subl;if (_pRoot == parent){_pRoot = subl;subl->_pParent = nullptr;}else{if (pparent->_pLeft == parent){pparent->_pLeft=subl;}else{pparent->_pRight=subl;}subl->_pParent = pparent;}subl->_bf = parent->_bf = 0;}// 左单旋void RotateL(Node* parent){Node* subr = parent->_pRight;Node* subrl = subr->_pLeft;parent->_pRight = subrl;if (subrl)subrl->_pParent = parent;Node* pparent = parent->_pParent;parent->_pParent = subr;if (parent==_pRoot){_pRoot = subr;subr->_pParent = nullptr;}else{if (pparent->_pLeft == parent){pparent->_pLeft=subr;}else{pparent->_pRight=subr;}subr->_pParent = pparent;}subr->_bf = parent->_bf = 0;}// 右左双旋void RotateRL(Node* pParent){Node* subr = pParent->_pRight;Node* subrl = subr->_pLeft;int bf = subrl->_bf;RotateR(pParent->_pRight);RotateL(pParent); if (bf == 0){subr->_bf = subrl->_bf = pParent->_bf = 0;}else if (bf == 1){subrl->_bf =subr->_bf= 0;pParent->_bf = -1;}else if (bf == -1){pParent->_bf = subrl->_bf = 0;subr->_bf = 1;}}// 左右双旋void RotateLR(Node* pParent){Node* subl = pParent->_pLeft;Node* sublr = subl->_pRight;int bf = sublr->_bf;RotateL(pParent->_pLeft);RotateR(pParent);if (bf == 0){subl->_bf = sublr->_bf = pParent->_bf = 0;}else if (bf == -1){subl->_bf = sublr->_bf = 0;pParent->_bf = 1;}else if (bf == 1){pParent->_bf =sublr->_bf = 0;subl->_bf = -1;}}private:Node* _pRoot;
};

 

 

 

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

相关文章:

  • 和君咨询公司seo优化教程下载
  • html简单的网站淘宝指数官网的网址
  • 自己给网站做支付接口网站手机版排名seo
  • 国内做五金加工的订单网站湖南关键词优化排名推广
  • discuz 旅游网站模版百度开户多少钱
  • 毕业设计 网站开发天津网站建设优化
  • 网站建设推广代理商抚顺网站seo
  • 巢湖路桥建设集团有限公司网站推广软件平台
  • 网站开发 创造收益免费建站系统
  • 域名网站搭建网站优化分析
  • 网站建设评比办法网络营销的五个发展阶段
  • 艺腾青岛网站建设外贸网站推广与优化
  • 电商网站分析报告网络营销的发展历程
  • wordpress 整站下载百度seo指数查询
  • 看国外的视频用什么浏览器批量优化网站软件
  • 奇艺广州网站建设熊掌号网络营销的基本内容有哪些
  • 室内装修免费咨询河南整站关键词排名优化软件
  • 成都娱乐场所最新消息网站更换服务器对seo的影响
  • 深圳wap网站建设网络推广的方法有
  • 智能手机网站建设百度网页版登录
  • 江苏网页设计报价seo 推广服务
  • 工程科技 网站设计网络营销与网站推广的区别
  • wordpress多站点统计网上商城建设
  • 济南网站营销网络营销的种类
  • 云南学校 手机网站建设新产品推广方式有哪些
  • 建立网站的公司有哪些网络销售适合什么人做
  • 建设智能家居网站SWOT分析网站制作公司哪家好
  • 企业网站托管如何更有效优化百度涨
  • 黑龙江网站建设巨耀网络网站一般需要怎么推广
  • 网站 php连接mysql 代码重庆网站推广专家