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

做网站py和php列表网推广效果怎么样

做网站py和php,列表网推广效果怎么样,优秀 响应式网站,网站建设方案书⭐上篇文章:34.二叉树进阶3(CSTL 关联式容器,set/map的介绍与使用)-CSDN博客 ⭐本篇代码:c学习/19.map和set的使用用与模拟 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) ⭐标⭐是比较重要的部分 一. 二…

⭐上篇文章:34.二叉树进阶3(C++STL 关联式容器,set/map的介绍与使用)-CSDN博客

⭐本篇代码:c++学习/19.map和set的使用用与模拟 · 橘子真甜/c++-learning-of-yzc - 码云 - 开源中国 (gitee.com)

⭐标⭐是比较重要的部分

一. 二叉搜索树的缺点

        之前文章中提到,普通的二叉搜索树在某些情况下会退出成链表,或者根节点的左右子树的高度差非常大。这个时候就会导致其搜索效率由 O(logN) -> O(N)。

        为了解决这个问题,计算机科学家提供了AVL树。AVL树一种平衡二叉搜索树,通过平衡因子和旋转操作来保证二叉搜索树是平衡的。

二. AVL树及其特点

1 AVL树是一颗二叉搜索树,满足二叉搜索树的性质

2 AVL树每一个节点中有一个平衡因子,表示该节点左右子树的高度差的绝对值,且该值不能超过1(即左右子树高度差不能超过1)

        可以看到,通过平衡因子可以保证AVL树是高度平衡的!AVL树在每一次插入新节点之后都要检验该节点和其父节点的平衡因子,一旦检测到平衡因子的值超过1,就要通过旋转操作来调整平衡因子。

三. AVL树的节点和旋转操作图解

3.1 AVL树节点

//节点
template<class K, class V>
struct AVLTreeNode
{AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;//节点的双亲,用于更新平衡因子int _bf;//平衡因子 balance factor pair<K, V> _kv;//构造函数AVLTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv){}
};

二叉树一般都是存储键值对<k,v>。AVL树需要一个平衡因子bf

3.2 AVL树结构 

template<class K, class V>
class AVlLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv){}
private:Node* _root;
};

3.3 AVL树的插入操作 ⭐

        AVL树的插入操作和二叉搜索树几乎一样,不过在插入节点之后要根据平衡因子才调整整棵树的结构。

a 左单旋

        如果一个节点的平衡因子为2,即右子树比左子树高2则需要对该节点进行左单旋

代码如下:

//右右,左单旋.一共需要调整6条线,四个节点void RotateLeft(Node* parent){if (!parent)return;Node* ppNode = parent->_parent;//要旋转节点的父亲Node* SubR = parent->_right;//要旋转节点的右孩子Node* SubRLeft = SubR->_left;//要旋转节点右孩子的左孩子//一:调整节点parent->_right = SubRLeft;if (SubRLeft)SubRLeft->_parent = parent;SubR->_left = parent;parent->_parent = SubR;//1.parent是根,现在SubR是根//2.parent是整棵树的子树,找到其父亲,旋转完成后,让subR与其父亲相连接if (_root == parent){_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;}

b 右单旋 

        如果一个节点的左子树比右子树高2,则需要对该节点进行右单旋

代码如下:

//左左,右单旋void RotateRight(Node* parent){if (!parent)return;Node* ppNode = parent->_parent;Node* SubL = parent->_left;Node* SubLRight = SubL->_right;//1.旋转,调整节点parent->_left = SubLRight;if (SubLRight)SubLRight->_parent = parent;SubL->_right = parent;parent->_parent = SubL;if (_root == parent){_root = SubL;SubL->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = SubL;}else{ppNode->_right = SubL;}SubL->_parent = ppNode;}//2.更新平衡因子//旋转之后,subL为子树根,左子树高度为h+1,右子树为h+parent高度1.左右子树高度一样,平衡因子为0//parent左右子树高度也相等,平衡因子为0parent->_bf = SubL->_bf = 0;}

c 左双旋

        如果新增节点在较高右子树的左侧,则需要两次旋转。如下图

双旋可以复用单旋的代码

//右左void RotateRightLeft(Node* parent){//注意控制三个节点的平衡因子Node* SubR = parent->_right;Node* SubRL = SubR->_left;int bf = SubRL->_bf;RotateRight(parent->_right);    //上图旋转10RotateLeft(parent);             //上图旋转5//对应图来理解平衡因子if (bf == -1)//右左节点的左边插入{parent->_bf = 0;SubR->_bf = 1;}else if (bf == 1)//右左节点的右边插入{SubR->_bf = 0;parent->_bf = -1;}else if (bf == 0)//此时SubRL就是新增节点{parent->_bf = 0;SubR->_bf = 0;}//此时右左节点是根节点SubRL->_bf = 0;}

 c 右双旋

        如果新增节点在较高左子树的右侧,则需要两次旋转。如下图

//左右,先左旋parent->left,再右旋parentvoid RotateLeftRight(Node* parent){Node* SubL = parent->_left;Node* SubLR = SubL->_right;int bf = SubLR->_bf;RotateLeft(SubL);    //上图旋转5RotateRight(parent); //上图旋转10//更新平衡因子if (bf == 1){parent->_bf = 0;SubL->_bf = -1;}else if (bf == -1){SubL->_bf = 0;parent->_bf = 1;}else if (bf == 0){SubL->_bf = 0;parent->_bf = 0;}//左右节点为根节点SubLR->_bf = 0;}

注意,每一次旋转之后都要更新平衡因子

四. 二叉树插入完整代码

#pragma once
#include<iostream>
#include<queue>
#include<string>
using namespace std;//AVL树		(高度平衡二叉搜索树)
//1.是二叉搜索树
//2.树及所有子树都要满足左右左右子树的高度差不超过1//为了方便实现,我们在这里引入了平衡因子的概念,其值范围只能是0,1,-1(平衡因子不是必须的)
//平衡因子=右子树的高度-左子树的高度
//这样就能够控制其高度位O(logN)//节点
template<class K, class V>
struct AVLTreeNode
{AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;//节点的双亲,用于更新平衡因子int _bf;//平衡因子 balance factor pair<K, V> _kv;//构造函数AVLTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv){}
};//AVLTree
//1.按照搜索树的规则插入
//2.更新平衡因子
//3.如果没有出现违规的平衡因子,插入结束
//4.如果有存在违规的平衡因子,需要旋转
template<class K, class V>
class AVlLTree
{typedef AVLTreeNode<K, V> Node;
public://一个节点的插入,只会影响其祖先的平衡因子,所以只要判断其祖先的平衡因子即可//1.如果cur是其父亲的左,parent->_bf--.如果cur是其父亲的右,parent->_bf++//2.在这些祖先中,更新完,parent->_bf==0,说明parent的高度不变,更新结束,插入完成(把这颗parent为根的子树矮的填上了)//3.更新完parent,parent->_bf==1 or -1,parent高度变了,继续往上更新(说明更新前parent->_bf==0,parent的高度变了)\//4.如果更新完parent的bf,parent->_bf==2, or -2,parent的所在子树不平衡,需要旋转处理,旋转后插入结束bool Insert(const pair<K, V>& kv){//1.先按搜索树进行插入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->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv);if (parent->_kv.first > kv.first){parent->_left = cur;cur->_parent = parent;//要将cur与其父亲链接}else{parent->_right = cur;cur->_parent = parent;}//2.从插入节点开始对这个节点及所有祖先节点更新平衡因子while (parent){if (parent->_right == cur){parent->_bf++;}else{parent->_bf--;}if (parent->_bf == 0){//parent所在子树高度不变,更新结束break;}else if (parent->_bf == 1 || parent->_bf == -1){//parent所在子树高度变了,有0变1或者-1,此时继续向上更新cur = parent;parent = parent->_parent;}else //if (parent->_bf == 2 || parent->_bf == -2){//parent所在子树出现问题,需要旋转处理//1.旋转完成后,它还得是完整的搜索树//2.旋转完成后,它要变平衡//旋转方法if (parent->_bf == 2)//左旋{if (cur->_bf == 1)//右右,直接对parent左单旋{//1.左单旋//将subR的左边给parent的右边(parent的右边指向subR的左边)//将parent变为subR的左边(subR的左边指向parent)RotateLeft(parent);}else if (cur->_bf == -1)//右左,先对parent->right右单旋,再对parent左单旋{//左双旋//先右单旋cur,让parent变为右右//再左单旋parentRotateRightLeft(parent);} }else if (parent->_bf == -2){	if (cur->_bf == -1)//左左,直接对parent右单旋{//右单旋RotateRight(parent);}else if (cur->_bf == 1)//左右,对parent->left左单旋,再对parent右单旋{//右双旋//先左单旋cur,让parenttt变为左左//再右单旋parent//此时parent左右这个节点为根RotateLeftRight(parent);}}//旋转完成后之间跳出即可,这是由于旋转让我平衡了,高度恢复到了插入新节点之前的高度(即高度不会变化)//如果是子树,对上层节点不会有影响。更新结束,跳出即可break;			}}return true;}void InOrder(){_InOrder(_root);cout << endl;}
private://右右,左单旋.一共需要调整6条线,四个节点void RotateLeft(Node* parent){if (!parent)return;Node* ppNode = parent->_parent;//要旋转节点的父亲Node* SubR = parent->_right;//要旋转节点的右孩子Node* SubRLeft = SubR->_left;//要旋转节点右孩子的左孩子//一:调整节点parent->_right = SubRLeft;if (SubRLeft)SubRLeft->_parent = parent;SubR->_left = parent;parent->_parent = SubR;//1.parent是根,现在SubR是根//2.parent是整棵树的子树,找到其父亲,旋转完成后,让subR与其父亲相连接if (_root == parent){_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 RotateRight(Node* parent){if (!parent)return;Node* ppNode = parent->_parent;Node* SubL = parent->_left;Node* SubLRight = SubL->_right;//1.旋转,调整节点parent->_left = SubLRight;if (SubLRight)SubLRight->_parent = parent;SubL->_right = parent;parent->_parent = SubL;if (_root == parent){_root = SubL;SubL->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = SubL;}else{ppNode->_right = SubL;}SubL->_parent = ppNode;}//2.更新平衡因子//旋转之后,subL为子树根,左子树高度为h+1,右子树为h+parent高度1.左右子树高度一样,平衡因子为0//parent左右子树高度也相等,平衡因子为0parent->_bf = SubL->_bf = 0;}//右左void RotateRightLeft(Node* parent){//注意控制三个节点的平衡因子Node* SubR = parent->_right;Node* SubRL = SubR->_left;int bf = SubRL->_bf;RotateRight(parent->_right);RotateLeft(parent);//对应图来理解平衡因子if (bf == -1)//右左节点的左边插入{parent->_bf = 0;SubR->_bf = 1;}else if (bf == 1)//右左节点的右边插入{SubR->_bf = 0;parent->_bf = -1;}else if (bf == 0)//此时SubRL就是新增节点{parent->_bf = 0;SubR->_bf = 0;}//此时右左节点是根节点SubRL->_bf = 0;}//左右,先左旋parent->left,再右旋parentvoid RotateLeftRight(Node* parent){Node* SubL = parent->_left;Node* SubLR = SubL->_right;int bf = SubLR->_bf;RotateLeft(SubL);RotateRight(parent);if (bf == 1){parent->_bf = 0;SubL->_bf = -1;}else if (bf == -1){SubL->_bf = 0;parent->_bf = 1;}else if (bf == 0){SubL->_bf = 0;parent->_bf = 0;}//左右节点为根节点SubLR->_bf = 0;}//中序遍历辅助函数void _InOrder(Node* root){if (!root)return;_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << " 平衡因子:" << root->_bf << endl;_InOrder(root->_right);}Node* _root;
};

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

相关文章:

  • 包头网站建设推广nba湖人队最新消息
  • 有哪些做的推文排版的网站关键字挖掘
  • 可以免费做网站吗百度seo怎么样优化
  • 动态网站开发大赛名字阿里指数查询
  • 网站文案设计百度电脑版下载安装
  • 网站开发asp最有效的15个营销方法
  • 怎么切图做网站网络营销推广的方法
  • 深圳西乡 网站建设sem培训班
  • 平台网站怎么做的好2022网站seo
  • 网站找哪家做全自动在线网页制作
  • 公司英文网站建设武汉网络推广网络营销
  • 美国网站建站宁波seo快速优化公司
  • 福建seo外包seo辅助工具
  • 做食物外网视频网站百度有哪些产品
  • 深圳网站建设公司排名网上软文发稿平台
  • 南汇做网站公司比较成功的网络营销案例
  • 万网 网站建设合同百度seo综合查询
  • 做网站 需要了解什么电商网站推广方案
  • 兰州网站建设尚美市场营销手段13种手段
  • 河北手机网站制作哪家好泰安做网站公司哪家比较好
  • 如何开始做婚恋网站魔贝课凡seo课程好吗
  • 网站建设广告图seo关键词排名怎么提升
  • 商丘做网站哪家好西安seo黑
  • 做个网站需要学会什么网址域名ip解析
  • asp做网站和dw的区别网络营销的主要推广方式
  • 淄博 网站设计株洲企业seo优化
  • 某些网站dns解析失败seo收费标准多少
  • 柳州企业网站建设it培训机构靠谱吗
  • 怎么提高网站加载速度慢seo优化软件哪个好
  • 网站开发后端用java叫什么做app软件大概多少钱