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

电商加盟网站建设百度知道

电商加盟网站建设,百度知道,吉林做网站,做故障风的头像的网站一、AVL树概念 AVL树,又称为平衡二叉树,它基于二叉搜索树并通过平衡而得到。 在前面的学习中我们提到,二叉搜索树可以提高搜索数据的效率,但在数据有序的情况下会退化为单支树,此时在树中查找元素就得遍历一整个分支…

一、AVL树概念

AVL树,又称为平衡二叉树,它基于二叉搜索树并通过平衡而得到。

在前面的学习中我们提到,二叉搜索树可以提高搜索数据的效率,但在数据有序的情况下会退化为单支树,此时在树中查找元素就得遍历一整个分支,时间复杂度也会退化至O(N)。

在这里插入图片描述

如果可以采用某种方式使作用两边可以达到平衡,便可以很好的平衡效率问题。

因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了AVL树,解决了上述问题。


二、AVL树性质

AVL树是最先发明的自平衡二叉查找树,AVL是一颗空树,或者具备下列性质的二叉搜索树:它的左右子树都是AVL树,且左右子树的高度差的绝对值不超过1。AVL树是一颗高度平衡搜索二叉树,通过控制高度差去控制平衡

这里规定,在一个结点左边插入结点,该结点平衡因子–,反之则++。

AVL树的性质如下:

  • AVL树可以是空树
  • 一颗AVL树的左右子树都是AVL树
  • 一颗AVL树的左右子树高度差不超过1

在这里插入图片描述

左图为AVL树,右图则不是


三、AVL树实现

一个AVL树想要维持住它的平衡,平衡因子肯定是必不可少的,那么,想一想,我们只考虑当前结点的平衡因子吗?上图的情况是不是要考虑到?既然考虑到父亲结点了,那么爷爷结点要不要考虑到?答案是不用的,爷爷结点的调整一定是基于父亲结点和叔叔结点的,所以我们调整时需要一层一层往上调整,只需考虑父亲结点的平衡因子是否符合条件。所以,一个AVL树结点中要包含:指向两个孩子的指针,父亲结点,平衡因子。

struct AVLTreeNode
{// 需要parent指针,后续更新平衡因子可以看到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){}
};

3.1 插入

AVL树插入过程和二叉搜索树类似,都是和key值进行比较,这里重点讨论:插入数据后如何维持平衡。

当插入数据后会出现两种情况:

  1. 当前结点父结点平衡因子< ±1,这种情况无需处理
  2. 当前结点父结点平衡因子>±1,这种情况需要处理

在这里插入图片描述

结点平衡因子调整过程和上图类似,一层一层向上调整,直到不用调整为止,但如果某个结点的平衡因子>±1,则不在调整,转而进行处理,根据这种思想,写出代码如下:

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--;elseparent->_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){//进行处理    }else{assert(false);}}return true;
}

3.2 旋转

要进行搜索树的平衡,可对结点进行旋转实现。在这里插入图片描述

对于该这个搜索树,如何使其平衡呢?这个时候,进行一个左单旋即可维持平衡。

在这里插入图片描述

旋转总共分为四种,左单旋/右单旋/左右双旋/右左双旋。

3.2.1左单旋

关于左单旋发生的场景为:右边高了,为了维持平衡,一定要往左边增加结点,右边减少结点。

在这里插入图片描述

这样旋转之后,便达到了平衡且不影响上一层。这里直接用抽象模型进行演示,说明该规律具有普遍性,这里回答一下为什么一定那两个b长度是相同的:如果这两段长度不一致,一长一短,则一定会进行调整因为破坏了AVL的形成条件。

左单旋实现

void RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;if (parentParent == nullptr){_root = subR;subR->_parent = nullptr;}else{if (parent == parentParent->_left){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;
}
3.2.2右单旋

右单旋和左单旋类似,当左边高了,就需要向右旋转,来维持高度平衡。

在这里插入图片描述

右单旋代码实现

void RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* pParent = parent->_parent;subL->_right = parent;parent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (pParent->_left == parent){pParent->_left = subL;}else{pParent->_right = subL;}subL->_parent = pParent;}subL->_bf = 0;parent->_bf = 0;
}
3.2.3左右双旋

在这里插入图片描述

针对这棵树,不管进行左/右单旋都无法解决问题,所以便要对其进行双旋,即先对14这个结点进行左旋,对旋转之后的再来一个右旋,即可平衡。

在这里插入图片描述

左右双旋代码实现

void RotateLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == -1){subLR->_bf = 0;subL->_bf = 0;parent->_bf = 1;}else if (bf == 1){subLR->_bf = 0;subL->_bf = -1;parent->_bf = 0;}else if (bf == 0){subLR->_bf = 0;subL->_bf = 0;parent->_bf = 0;}else{assert(false);}
}
3.2.4 右左双旋

在这里插入图片描述

这个也是和左右双旋类似

在这里插入图片描述

总结:父节点和自己平衡因子符号相同,必定单旋,向平衡因子小的一边旋转;相反则双旋,旋转方法类似。如实在不明白就画图自行推导即可。

左右双旋代码实现

void RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subR->_bf = 0;subRL->_bf = 0;parent->_bf = 0;}else if (bf == 1){subR->_bf = 0;subRL->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;subRL->_bf = 0;parent->_bf = 0;}else{assert(false);}
}

3.3 查找

查找和二叉搜索树类似,都是二分查找,时间复杂度O(logN)

Node* Find(const K& key)
{Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;
}

3.4 平衡检测

该如何检测这个是一个平衡二叉树呢?能不能通过平衡因子进行检测?当然不可以了,因为平衡因子就是咱们进行规定的,自然符合条件,所以必须提出另外一种检测办法。这里采用高度,计算一个结点两边高度,判断是否大于1即可。

bool _IsBalanceTree(Node* root)
{// 空树也是AVL树if (nullptr == root)return true;// 计算pRoot结点的平衡因子:即pRoot左右子树的高度差int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);int diff = rightHeight - leftHeight;// 如果计算出的平衡因子与pRoot的平衡因子不相等,或者// pRoot平衡因子的绝对值超过1,则一定不是AVL树if (abs(diff) >= 2){cout << root->_kv.first << "高度差异常" << endl;return false;}//进行判断平衡因子更新是否正确if (root->_bf != diff){cout << root->_kv.first << "平衡因子异常" << endl;return false;}// pRoot的左和右如果都是AVL树,则该树一定是AVL树return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);
}

3.5 有序检测

这里我们采用中序遍历,如若是升序,则该树是有序的

void _InOrder(Node* root)
{if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);
}

四、完整代码

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;template<class K, class V>
struct AVLTreeNode
{// 需要parent指针,后续更新平衡因子可以看到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--;elseparent->_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){RotateR(parent);}else if (parent->_bf == 2 && cur->_bf == 1){RotateL(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;}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* pParent = parent->_parent;subL->_right = parent;parent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (pParent->_left == parent){pParent->_left = subL;}else{pParent->_right = subL;}subL->_parent = pParent;}subL->_bf = 0;parent->_bf = 0;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;if (parentParent == nullptr){_root = subR;subR->_parent = nullptr;}else{if (parent == parentParent->_left){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;}void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == -1){subLR->_bf = 0;subL->_bf = 0;parent->_bf = 1;}else if (bf == 1){subLR->_bf = 0;subL->_bf = -1;parent->_bf = 0;}else if (bf == 0){subLR->_bf = 0;subL->_bf = 0;parent->_bf = 0;}else{assert(false);}}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subR->_bf = 0;subRL->_bf = 0;parent->_bf = 0;}else if (bf == 1){subR->_bf = 0;subRL->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;subRL->_bf = 0;parent->_bf = 0;}else{assert(false);}}void InOrder(){_InOrder(_root);cout << endl;}int Height(){return _Height(_root);}int Size(){return _Size(_root);}bool IsBalanceTree(){return _IsBalanceTree(_root);}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}private:void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);}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;}int _Size(Node* root){if (root == nullptr)return 0;return _Size(root->_left) + _Size(root->_right) + 1;}bool _IsBalanceTree(Node* root){// 空树也是AVL树if (nullptr == root)return true;// 计算pRoot结点的平衡因子:即pRoot左右子树的高度差int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);int diff = rightHeight - leftHeight;// 如果计算出的平衡因子与pRoot的平衡因子不相等,或者// pRoot平衡因子的绝对值超过1,则一定不是AVL树if (abs(diff) >= 2){cout << root->_kv.first << "高度差异常" << endl;return false;}if (root->_bf != diff){cout << root->_kv.first << "平衡因子异常" << endl;return false;}// pRoot的左和右如果都是AVL树,则该树一定是AVL树return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);}
private:Node* _root = nullptr;
};

完!

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

相关文章:

  • 2022最新通道地址1全面的seo网站优化排名
  • 重庆做网站公司有哪些5118数据分析平台官网
  • 成都网站建设外包公司排名班级优化大师官方免费下载
  • 社交网站图片展示太原seo外包公司
  • c2c电子商务网站有哪些营销手段和营销方式
  • 自建站成本广告网站大全
  • 做企业网站需要什么资料百度搜索引擎的特点
  • 在线网站制作系统源码百度网址大全免费下载
  • 网站怎样做移动端百度知道灰色词代发收录
  • 大连建设网站便民服务爱站网综合查询
  • 深圳龙岗做网站深圳网站建设公司
  • 网站开发合同存在的缺陷磁力猫最佳搜索引擎入口
  • 书荒小说阅读器是哪个网站做的杭州网站优化多少钱
  • 企业网站前端模板优化网站排名需要多少钱
  • 中国专业做鞋子的网站沈阳企业网站seo公司
  • 做php网站用什么软件好个人域名注册流程
  • 网站建设哪家公司如何做网络营销推广
  • 自己如何做独立网站seo搜索引擎优化就业指导
  • 专业做网站的温州seo排名公司
  • 宝鸡做网站公司海外广告优化师
  • 怎样找到网站建设设置模板漯河搜狗关键词优化排名软件
  • 网站 引导页 设计百度世界排名
  • 网站设计东莞怎么制作个人网页
  • 出版社网站建设长沙竞价优化
  • 网站源码交易平台代码seo的课谁讲的好
  • 自己建服务器做网站违法长沙网站推广排名
  • 政府门户网站建设合同现在推广平台哪家最好
  • e时代速递搜索引擎网站建设产品推销
  • k网站建设最新足球赛事
  • 建设网站破解版备案域名交易平台