文章目录

  • 8.6 二叉排序树
    • 8.6.1 二叉排序树查找操作
    • 8.6.2 二叉排序树插入操作
    • 8.6.3 二叉排序树删除操作
    • 8.6.4 二叉排序树总结
  • 8.7 平衡二叉树( AVL树 )
    • 8.7.1 平衡二叉树实现原理
    • 8.7.2 平衡二叉树实现算法

8.6 二叉排序树

假设查找的数据集是普通的顺序存储,那么插入操作就是将记录放在表的末端,给表记录数加一即可,删除操作可以是删除后,后面的记录向前移,也可以是要删除的元素与最后一个元素互换,表记录数减一,反正整个数据集也没有什么顺序,这样的效率也不错。应该说,插入和删除对于顺序存储结构来说,效率是可以接受的,但这样的表由于无序造成查找的效率很低。

如果查找的数据集是有序线性表,并且是顺序存储的,查找可以用折半、插值、 斐波那契等查找算法来实现,可惜,因为有序,在插入和删除操作上,就需要耗费大置的时间。

有没有一种即可以使得插入和删除效率不错,又可以比较高效率地实现查找的算法呢?还真有。

我们在 8.2 节把这种需要在查找时插入或删除的查找表称为动态查找表。我们现在就来看看什么样的结构可以实现动态查找表的高效率。

如果在复杂的问题面前,我们束手无策的话,不妨先从最最简单的情况入手。现在我们的目标是插入和查找同样高效。假设我们的数据集开始只有一个数 {62},然后现在需要将 88 插入数据集,于是数据集成了 {62,88},还保持着从小到大有序。再查找有没有 58 ,没有则插入,可此时要想在线性表的顺序存储中有序,就得移动 62 和 88 的位置,如图 8-6-2 左图,可不可以不移动呢?嗯,当然是可以,那就是二叉树结构。当我们用二叉树的方式时,首先我们将第一个数 62 定为根结点, 88 因为比 62 大,因此让它做 62 的右子树,58 因比 62 小,所以成为它的左子树。此时 58 的插入并没有影响到 62 与 88 的关系,如图 8-6-2 右图所示。

在这里插入图片描述

也就是说,若我们现在需要对集合{ 62, 88, 58, 47, 35, 73, 51, 99, 37, 93 }做查找,在我们打算创建此集合时就考虑用二叉树结构,而且是排好序的二叉树来创建。如图 8-6-3 所示,62 、88 、58 创建好后,下一个数 47 因比 58 小,是它的左子树(见③),35 是 47 的左子树(见④),73 比 62 大,但却比 88 小,是 88 的左子树(见⑤), 51 比 62 小、比 58 小、比 47 大,是 47 的右子树(见⑥), 99 比 62 、 88 都大,是 88 的右子树(见⑦), 37 比 62 、 58 、 47 都小,但却比 35 大,是 35 的右子树(见⑧), 93 则因比 62 、 88 大是 99 的左子树(见⑨)。

在这里插入图片描述

这样我们就得到了一棵二叉树,并且当我们对它进行中序遍历时,就可以得到一个有序的序列{ 35, 37, 47, 51, 58, 62, 73, 88, 93, 99 },所以我们通常称它为二叉排序树

二叉排序树( Binary Sort Tree ),又称为二叉査找树。它或者是一棵空树,或者是具有下列性质的二叉树

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结构的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉排序树。

从二叉排序树的定义也可以知道,它前提是二叉树,然后它采用了递归的定义方法,再者,它的结点间满足一定的次序关系,左子树结点一定比其双亲结点小,右子树结点一定比其双亲结点大。

构造一棵二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除关键字的速度。不管怎么说,在一个有序数据集上的查找,速度总是要快于无序的数据集的,而二叉排序树这种非线性的结构,也有利于插入和删除的实现。

8.6.1 二叉排序树查找操作

首先我们提供一个二叉树的结构:

/* 二叉树的二叉链表结点结构定义 */
typedef struct BiTNode	/* 结点结构 */
{int data;	/* 结点数据 */struct BiTNode *lchild, *rchild; /* 左右孩子指针 */
} BiTNode, *BiTree;

然后我们来看看二叉排序树的查找是如何实现的。

#define TRUE 1
#define FALSE 0
typedef int Status; //创建子函数返回类型 
/* 递归查找二叉排序树 T 中是否存在 key , 指针 f 指向 T 的双亲,其初始调用值为NULL */
/* 若查找成功,则指针 p 指向该数据元素结点,并返回 TRUE */
/* 否则指针 p 指向查找路径上访问的最后一个结点并返回 FALSE */
Status SearchBST(BiTree T, int key, BiTree f, BiTree *p)
{if (!T)	/* 查找不成功 */{*p = f;return FALSE;}else if (key == T->data)	/* 查找成功 */{*p = T;return TRUE;}else if (key < T->data){return SearchBST(T->lchild , key, T, p); /*在左子树继续查找 */}else{return SearchBST(T->rchild, key, T, p); /*在右子树继续查找 */}
}
  1. SearchBST 函数是一个可递归运行的函数,函数调用时的语句为 SearchBST(T,93,NULL,p) ,参数 T 是一个二叉链表,其中数据如图 8-6-3 所示,key 代表要查找的关键字,目前我们打算查找 93 ,二叉树 f 指向 T 的双亲,当 T 指向根结点时,f 的初值就为 NULL ,它在递归时有用,最后的参数 P 是为了査找成功后可以得到查找到的结点位置。

    在这里插入图片描述

  2. 第 9〜13 行,是用来判断当前二叉树是否到叶子结点,显然图 8-6-3 告诉我们当前 T 指向根结点 62 的位置,T 不为空,第 11〜12 行不执行。

  3. 第 14〜18 行是查找到相匹配的关键字时执行语句,显然 93≠62 ,第 16〜17 行不执行。

  4. 第 19〜22 行是当要查找关键字小于当前结点值时执行语句,由于 93>62 ,第 21 行不执行。

  5. 第 23〜26 行是当要查找关键字大于当前结点值时执行语句,由于 93>62 ,所以递归调用 SearchBST(T->rchild, key, T, p) 。此时 T 指向了 62 的右孩子 88 ,如图 8-6-4 所示。

    在这里插入图片描述

  6. 此时第二层 SearchBST ,因 93 比 88 大,所以执行第 25 行,再次递归调用 SearchBST(T->rchild, key, T, p) 。此时 T 指向了 88 的右孩子 99 ,如图 8-6-5 所示。

    在这里插入图片描述

  7. 第三层的 SearchBST ,因 93 比 99 小,所以执行第 21 行,递归调用 SearchBST( T->lchild, key, T, p ) 。此时 T 指向了 99 的左孩子 93 ,如图 8-6-6 所示。

    在这里插入图片描述

  8. 第四层 SearchBST ,因 key 等于 T->data ,所以执行第 16〜17 行,此时指针 p 指向 93 所在的结点,并返回 True 到第三层、第二层、第一层,最终函数返回 True 。

8.6.2 二叉排序树插入操作

有了二叉排序树的查找函数,那么所谓的二叉排序树的插入,其实也就是将关键字放到树中的合适位置而已,来看代码。

#define TRUE 1
#define FALSE 0
typedef int Status; //创建子函数返回类型 
/* 当二叉排序树T中不存在关键字等于 key 的数据元素时,*/
/* 插入 key 并返回 TRUE ,否則返回 FALSE */
Status InsertBST(BiTree *T,int key)
{BiTree p, s;if (!SearchBST(*T, key, NULL, &p))	/* 查找不成功 */{s = (BiTree)malloc(sizeof (BiTNode));s->data = key;s->lchild = s->rchild = NULL;if (!p){*T = s;	/* 插入 s 为新的根结点 */}else if (key < p->data){p->lchild = s; /* 插入 s 为左孩子 */}else{p->rchild = s; /* 插入 s 为右孩子 */}return TRUE;}elsereturn FALSE;	/* 树中已有关键字相同的结点,不再插入 */
}

这段代码非常简单。如果你调用函数是 “InsertBST(T, 93);” ,那么结果就是 FALSE ,如果是 “InsertBST (T,95);” ,那么一定就是在 93 的结点增加一个右孩子 95 ,并且返回 True 。如图 8-6-7 所示。

在这里插入图片描述
有了二叉排序树的插入代码,我们要实现二叉排序树的构建就非常容易了。下面的代码就可以创建一棵图 8-6-3 这样的树。

int i;
int a[10] = {62,88,58,47,35,73,51,99,37,93};
BiTree T=NULL;
for(i=0;i<10;i++)
{InsertBST(&T,a[i]);
}

8.6.3 二叉排序树删除操作

俗话说 “请神容易送神难” ,我们已经介绍了二叉排序树的查找与插入算法,但是对于二叉排序树的删除,就不是那么容易,我们不能因为删除了结点,而让这棵树变得不满足二叉排序树的特性,所以删除需要考虑多种情况。

如果需要查找并删除如 37 、51 、73 、93 这些在二叉排序树中是叶子的结点,那是很容易的,毕竟删除它们对整棵树来说,其他结点的结构并未受到影响,如图 8-6-8 所示。

在这里插入图片描述

对于要删除的结点只有左子树或只有右子树的情况,相对也比较好解决。那就是结点删除后,将它的左子树或右子树整个移动到删除结点的位置即可,可以理解为独子继承父业。比如图 8-6-9,就是先删除 35 和 99 结点,再删除 58 结点的变化图,最终,整个结构还是一个二叉排序树。

在这里插入图片描述

但是对于要删除的结点既有左子树又有右子树的情况怎么办呢?比如图 8-6-10 中的 47 结点若要删除了,它的两儿子以及子孙们怎么办呢?

在这里插入图片描述

起初的想法,我们当 47 结点只有一个左子树,那么做法和一个左子树的操作一 样,让 35 及它之下的结点成为 58 的左子树,然后再对 47 的右子树所有结点进行插入操作,如图 8-6-11 所示。这是比较简单的想法,可是 47 的右子树有子孙共 5 个结点,这么做效率不高且不说,还会导致整个二叉排序树结构发生很大的变化,有可能会增加树的高度。增加高度可不是个好事,这我们待会再说,总之这个想法不太好。

在这里插入图片描述

我们仔细观察一下,47 的两个子树中能否找出一个结点可以代替 47 呢?果然有,37 或者 48 都可以代替 47 ,此时在删除 47 后,整个二叉排序树并没有发生什么本质的改变。

为什么是 37 和 48 ? 对的,它们正好是二叉排序树中比它小或比它大的最接近 47 的两个数。也就是说,如果我们对这棵二叉排序树进行中序遍历,得到的序列 { 29, 35, 36, 37, 47, 48, 49, 50, 51, 56, 58, 62, 73, 88, 93, 99 },它们正好是 47 的前驱和后继。

因此,比较好的办法就是,找到需要删除的结点 p 的直接前驱(或直接后继) s , 用 s 来替换结点 p ,然后再删除此结点 s ,如图 8-6-12 所示。

在这里插入图片描述

根据我们对删除结点三种情况的分析:

  • 叶子结点;
  • 仅有左或右子树的结点;
  • 左右子树都有的结;

我们来看代码,下面这个算法是递归方式对二叉排序树 T 査找 key ,查找到时删除。

typedef int Status; //创建子函数返回类型 
/* 若二叉排序树T中存在关键字等于 key 的数据元素时,则删除该数据元素结点,*/
/* 并返回 TRUE ;否則返回 FALSE */
Status DeleteBST(BiTree *T, int key)
{if(!*T) /* 不存在关键字等于 key 的数据元素 */{return FALSE;}else{if(key == (*T)->data) /* 找到关键字等于 key 的数据元素 */{return Delete(T);}else if(key < (*T)->data){return DeleteBST(&(*T)->lchild, key);}else {return DeleteBST(&(*T)->rchild, key);}}
}

这段代码和前面的二叉排序树查找几乎完全相同,唯一的区别就在于第 14 行,此时执行的是 Delete 方法,对当前结点进行删除操作。我们来看 Delete 的代码。

typedef int Status; //创建子函数返回类型 
/*从二叉排序树中删除结点P,并重接它的左或右子树。*/
Status Delete(BiTree *p)
{BiTree q, s;if ((*p)->rchild = NULL)	/* 右子树空则只需重接它的左子树 */{q = *p;*p = (*p)->lchild;free(q);}else if ((*p)->lchild == NULL)	/* 只需重接它的右子树 */{q = *p;*p = (*p)->rchild;free(q);}else /* 左右子树均不空 */{q = *p;s = (*p)->lchild;while(s->rchild) /* 转左,然后向右到尽头(找待测结点的前驱)*/{q = s;s - s->rchild;}(*p)->data = s->data;	/* s 指向被删结点的直接前驱 */if (q != *p){q->rchild = s->lchild;	/* 重接 q 的右子树 */}else{q->lchilds = s->lchild;	/* 重接 q 的左子树 */}free(s);}return TRUE;
}

从这段代码也可以看出,我们其实是在找删除结点的前驱结点替换的方法,对于用后继结点来替换,方法上是一样的。

8.6.4 二叉排序树总结

总之,二叉排序树是以链接的方式存储,保持了链接存储结构在执行插入或删除操作时不用移动元素的优点,只要找到合适的插入和删除位置后,仅需修改链接指针即可。插入删除的时间性能比较好。而对于二叉排序树的查找,走的就是从根结点到要查找的结点的路径,其比较次数等于给定值的结点在二叉排序树的层数。极端情况,最少为 1 次,即根结点就是要找的结点,最多也不会超过树的深度。也就是说,二叉排序树的查找性能取决于二叉排序树的形状。可问题就在于,二叉排序树的形状是不确定的

例如 { 62, 88, 58, 47, 35, 73, 51, 99, 37, 93 } 这样的数组,我们可以构建如下图左图的二叉排序树。但如果数组元素的次序是从小到大有序,如 { 35, 37, 47, 51, 58, 62, 73, 88, 93, 99 } ,则二叉排序树就成了极端的右斜树,注意它依然是一棵二叉排序树,如图 8-6-19 的右图。此时,同样是查找结点 99 ,左图只需要两次比较,而右图就需要 10 次比较才可以得到结果,二者差异很大。

在这里插入图片描述

也就是说,我们希望二叉排序树是比较平衡的,即其深度与完全二叉树相同,均为 [log2n]+1 ,那么查找的时间复杂也就为 O(logn) 近似于折半查找,事实上,图 8-6-18 的左图也不够平衡,明显的左重右轻。

不平衡的最坏情况就是像上图右图的斜树,查找时间复杂度为 O(n) ,这等同于顺序查找。

因此,如果我们希望对一个集合按二叉排序树查找,最好是把它构建成一棵平衡的二叉排序树。这样我们就引申出另一个问题,如何让二叉排序树平衡的问题

8.7 平衡二叉树( AVL树 )

平衡二叉树( Self-Balancing Binary Search Tree 或 Height-Balanced Binary Search Tree ),是一种二叉排序树,其中每一个节点的左子树和右子树的髙度差至多等于 1

有两位俄罗斯数学家 G.M.Adelson-Velskii 和 E.M.Landis 在 1962 年共同发明一种解决平衡二叉树的算法,所以有不少资料中也称这样的平衡二叉树为 AVL 树

从平衡二叉树的英文名字,你也可以体会到,它是一种髙度平衡的二叉排序树。 那什么叫做高度平衡呢?意思是说,要么它是一棵空树,要么它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。我们将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子 BF ( Balance Factor ),那么平衡二叉树上所有结点的平衡因子只可能是 -1、 0 和 1 。只要二叉树上有一个结点的平衡因子的绝对值大于 1 ,则该二叉树就是不平衡的。

看图 8-7-2 ,为什么图 1 是平衡二叉树,而图 2 却不是呢?这里就是考查我们对平衡二叉树的定义的理解,它的前提首先是一棵二叉排序树,右上图的 59 比 58 大, 却是 58 的左子树,这是不符合二叉排序树的定义的。图 3 不是平衡二叉树的原因就在于,结点 58 的左子树高度为 3 ,而右子树为 1,二者差大于了绝对值 1 ,因此它也不是平衡的。而经过适当的调整后的图 4 ,它就符合了定义,因此它是平衡二叉树。

在这里插入图片描述

距离插入结点最近的,且平衡因子的绝对值大于 1 的结点为根的子树,我们称为最小不平衡子树。图 8-7-3 中,当新插入结点 37 时,距离它最近的平衡因子绝对值超过 1 的结点是 58 ( 即它的左子树高度 2 减去右子树高度 0 ),所以从 58 开始以下的子树为最小不平衡子树。

在这里插入图片描述

8.7.1 平衡二叉树实现原理

平衡二叉树构建的基本思想就是在构建二叉排序树的过程中,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树

为了能在讲解算法时轻松一些,我们先讲一个平衡二叉树构建过程的例子。假设我们现在有一个数组 a[10]={ 3, 2, 1, 4, 5, 6, 7, 10, 9, 8 } 需要构建二叉排序树。在没有学习平衡二叉树之前,根据二叉排序树的特性,我们通常会将它构建成如图 8-7-4 的图 1 所示的样子。虽然它完全符合二叉排序树的定义,但是对这样高度达到 8 的二叉树来说,查找是非常不利的。我们更期望能构建成如图 8-7-4 的图 2 的样子,高度为 4 的二叉排序树才可以提供高效的查找效率。那么现在我们就来研究如何将一个数组构建出图 2 的树结构。

在这里插入图片描述

对于数组 a[10]={3, 2, 1, 4, 5, 6, 7, 10, 9, 8 } 的前两位 3 和 2,我们很正常地构建,到了第 3 个数 “1” 时,发现此时根结点 “3” 的平衡因子变成了 2 ,此时整棵树都成了最小不平衡子树,因此需要调整,如图 8-7-5 的图 1( 结点左上角数字为平衡因子 BF 值 )。因为 BF 值为正,因此我们将整个树进行右旋( 顺时针旋转 ),此时结点 2 成了根结点,3 成了 2 的右孩子,这样三个结点的 BF 值均为 0 ,非常的平衡,如图 8-7-5 的图 2 所示。

在这里插入图片描述

然后我们再增加结点 4 ,平衡因子没发生改变,如图 3 。增加结点 5 时,结点 3 的 BF 值为 -2 ,说明要旋转了。由于 BF 是负值,所以我们对这棵最小平衡子树进行左旋( 逆时针旋转 ),如图 4 ,此时我们整个树又达到了平衡。

继续,增加结点 6 时,发现根结点 2 的 BF 值变成了 -2 ,如图 8-7-6 的图 6 。所以我们对根结点进行了左旋,注意此时本来结点 3 是 4 的左孩子,由于旋转后需要满足二叉排序树特性,因此它成了结点 2 的右孩子,如图 7。增加结点 7 ,同样的左旋转,使得整棵树达到平衡,如图 8 和图 9 所示。

在这里插入图片描述

当增加结点 10 时,结构无变化,如图 8-7-7 的图 10 。再增加结点 9 ,此时结点 7 的 BF 变成了 -2 ,理论上我们只需要旋转最小不平衡子树 7、9、10 即可,但是如果左旋转后,结点 9 就成了 10 的右孩子,这是不符合二叉排序树的特性的,此时不能简单的左旋,如图 11 所示。

在这里插入图片描述

仔细观察图 11,发现根本原因在于结点 7 的 BF 是 -2 ,而结点 10 的 BF 是 1,也就是说,它们俩一正一负,符号并不统一,而前面的几次旋转,无论左还是右旋, 最小不平衡子树的根结点与它的子结点符号都是相同的。这就是不能直接旋转的关键。那怎么办呢?

不统一,不统一就把它们先转到符号统一再说,于是我们先对结点 9 和结点 10 进行右旋,使得结点 10 成了 9 的右子树,结点 9 的 BF 为 -1,此时就与结点 7 的 BF值符号统一了,如图 8-7-7 的图 12 所示。

这样我们再以结点 7 为最小不平衡子树进行左旋,得到图 8-7-8 的图 13 。接着插入 8,情况与刚才类似,结点 6 的 BF 是 -2,而它的右孩子 9 的 BF 是 1,如图 14 , 因此首先以 9 为根结点,进行右旋,得到图 15 ,此时结点 6 和结点 7 的符号都是负,再以 6 为根结点左旋,最终得到最后的平衡二叉树,如图 8-7-8 的图 16 所示。

在这里插入图片描述

西方有一句民谣是这样说的:“丢失一个钉子,坏了一只蹄铁;坏了一只蹄铁,折了一匹战马;折了一匹战马,伤了一位骑士;伤了一位骑士,输了一场战斗;输了一场战斗,亡了一个帝国。”相信大家应该有点明白,所谓的平衡二叉树,其实就是在二叉排序树创建过程中保证它的平衡性,一旦发现有不平衡的情况,马上处理,这样就不会造成不可收拾的情况出现。通过刚才这个例子,你会发现,当最小不平衡子树根结点的平衡因子 BF 是大于 1 时,就右旋,小于 -1 时就左旋,如上例中结点 1、5、6、7 的插入等。插入结点后,最小不平衡子树的 BF 与它的子树的 BF 符号相反时,就需要对结点先进行一次旋转以使得符号相同后,再反向旋转一次才能够完成平衡操作,如上例中结点 9、8 的插入时

8.7.2 平衡二叉树实现算法

好了,有这么多的准备工作,我们可以来讲解代码了。首先是需要改进二叉排序树的结点结构,增加一个 bf ,用来存储平衡因子。

/* 二叉树的二叉链表结点结构定义 */
typedef struct	BiTNode	 /* 结点结构 */
{int data;	/* 结点数据 */int bf;		/* 结点的平衡因子 */struct BiTNode *lchild, *rchild;	/* 左右孩子指针 */
} BiTNode, *BiTree;

然后,对于右旋操作,我们的代码如下。

/* 对以 p 为根的二叉排序树作右旋处理,*/
/* 处理之后 p 指向新的树根结点,即旋转处理之前的左子树的根结点 */
void R_Rotate(BiTree *P)
{BiTree L;L = (*P)->lchild;			/*	L 指向 P 的左子树根结点 */(*P)->lchild = L->rchild;	/* L 的右子树挂接为 P 的左子树 */L->rchild = (*P);*P = L;						/* P 指向新的根结点 */
}

此函数代码的意思是说,当传入一个二叉排序树 P ,将它的左孩子结点定义为 L,将 L 的右子树变成 P 的左子树,再将 P 改成 L 的右子树,最后将 L 替换 P 成为根结点。这样就完成了一次右旋操作,如图 8-7-9 所示。图中三角形代表子树,N 代表新增结点。

在这里插入图片描述

上面例子中的新增加结点 N ( 如下图的图 1 和图 2 ),就是右旋操作。

左旋操作代码如下:

/* 对以 P 为根的二叉排序树作 左旋 处理,*/
/* 处理之后 P 指向新的树根结点,即旋转处理之前的右子树的根结点 0 */
void L_Rotate(BiTree *P)
{BiTree R;R = (*P)->rchild;		/* R 指向P的右子树根结点*/(*P)->rchild = R->lchild;	/* R 的左子树挂接为 P 的右子树*/R->lchild = (*P);*P = R;				/* P 指向新的根结点*/
}

这段代码与右旋代码是对称的,在此不做解释了。上面例子中的新增结点 5、6、7( 如图 8-7-5 的图 4、5,图 8-7-6 的图 6、7、8、9 ),都是左旋操作。

现在我们来看左平衡旋转处理的函数代码。

#define LH +1	/* 左高 */
#define EH 0	/* 等高 */
#define RH -1	/* 右高 */
/* 对以指针 T 所指结点为根的二叉树作左平衡旋转处理 */
/* 本算法结束时,指针 T 指向新的根结点 */
void LeftBalance(BiTree *T)
{BiTree L, Lr;L = (*T)->lchild;	/* L 指向 T 的左子树根结点 */switch (L->bf){/* 检查 T 的左子树的平衡度,并作相应平衡处理 */case LH:	/* 新结点插入在 T 的左孩子的左子树上,要作单右旋处理 */(*T)->bf = L->bf = EH;R_Rotate(T);break;case RH:	/* 新结点插入在 T 的左孩子的右子树上,要作双旋处理 */Lr = L->rchild;	/* Lr 指向 T 的左孩子的右子树根 */switch (Lr->bf) /* 修改 T 及其左孩子的平衡因子 */{case LH: (*T)->bf = RH;L->bf = EH;break;case EH:	(*T)->bf = L->bf = EH;break;case RH:	(*T)->bf = EH;L->bf = LH;break;}Lr->bf = EH;L_Rotate(&(*T)->lchild);    /* 对 T 的左子树作左旋平衡处理 */R_Rotate(T);                /* 对 T 作右旋平衡处理 */}
}

首先,我们定义了三个常数变量,分别代表 1、0、-1 。

  1. 函数被调用,传入一个需调整平衡性的子树 T 。由于 LeftBalance 函数被调用时,其实是已经确认当前子树是不平衡状态,且左子树的高度大于右子树的高度。换句话说,此时 T 的根结点应该是平衡因子 BF 的值大于 1 的数。

  2. 第 9 行,我们将 T 的左孩子赋值给 L 。

  3. 第 10〜36 行是分支判断。

  4. 当 L 的平衡因子为 LH ,即为 1 时,表明它与根结点的 BF 值符号相同,因此,第 14 行,将它们的 BF 值都改为 0 ,并且第 15 行,进行右旋操作。操作的方式如图 8-7-9 所示。

  5. 当 L 的平衡因子为 RH ,即为 -1 时,表明它与根结点的 BF 值符号相反,此时需要做双旋处理。第 19〜32 行,针对 L 的右孩子 Lr 的 BF 作判断,修改根结点 T 和 L 的 BF 值。第 33 行将当前 Lr 的 BF 改为 0 。

  6. 第 34 行,对根结点的左子树进行左旋,如图 8-7-10 第二图所示。

  7. 第 35 行,对根结点进行右旋,如图 8-7-10 的第三图所示,完成平衡操作。

在这里插入图片描述

同样的,右平衡旋转处理的函数代码非常类似,直接看代码,不做讲解了。

我们前面例子中的新增结点 9 和 8 就是典型的右平衡旋转,并且双旋完成平衡的例子(如图 8-7-7 的图11、12,图 8-7-8 图14、15、16所示)。

有了这些准备,我们的主函数才算是正式登场了。

#define LH +1	/* 左高 */
#define EH 0	/* 等高 */
#define RH -1	/* 右高 */
#define TRUE 1
#define FALSE 0
typedef int Status; //创建子函数返回类型 
/* 若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个 */ 
/* 数据元素为 e 的新结点并返回 1 ,否则返回 0 。若因插入而使二叉排序树 */ 
/* 失去平衡,则作平衡旋转处理,布尔变量 taller 反映 T 长高与否。*/
Status InsertAVL(BiTree *T, int e, Status *taller)
{if (!*T){/* 插入新结点,树“长高”,置 taller 为 TRUE */*T = (BiTree)malloc(sizeof(BiTNode));(*T)->data = e;(*T)->lchild = (*T)->rchild = NULL;(*T)->bf = EH;*taller = TRUE;}else{if (e == (*T)->data){/* 树中已存在和 e 有相同关键字的结点则不再插入 */*taller = FALSE;return FALSE;}if (e < (*T)->data){/* 应继续在 T 的左子树中进行搜索 */if (!InsertAVL(&(*T>->lchild, e, taller))  /* 未插入 */{return FALSE;}if (taller) /* 已插入到 T 的左子树中且左子树“长高” */{switch ((*T)->bf) /* 检查 T 的平衡度 */{case LH: /* 原本左子树比右子树高,需要作左平衡处理 */LeftBalance(T);*taller = FALSE;break;case EH: /* 原本左右子树等高,现因左子树增高而树增高 */(*T)->bf = LH;*taller = TRUE;break;case RH: /* 原本右子树比左子树高,现左右子树等高 */(*T)->bf = EH;*taller = FALSE;break;}}}else{/* 应继续在 T 的右子树中进行搜索 */if (!InsertAVL(&(*T)->rchild, e, taller)) /* 未插入 */{return FALSE;}if (*taller) /* 已插入到 T 的右子树且右子树“长高” */{switch ((*T)->bf) /* 检查 T 的平衡度 */{case	LH: /* 原本左子树比右子树高,现左、右子树等高 */(*T)->bf = EH;*taller = FALSE;break;case	EH: /* 原本左右子树等高,现因右子树增高而树增高 */(*T)->bf = RH;*taller = TRUE;break;case	RH: /* 原本右子树比左子树高,需要作右平衡处理 */RightBalance(T);*taller = FALSE;break;}}}}return TRUE;
}
  1. 程序开始执行时,第 12〜20 行是指当前 T 为空时,则申请内存新增一个结点。

  2. 第 23〜28 行表示当存在相同结点,则不需要插入。

  3. 第 29〜54 行,当新结点 e 小于 T 的根结点值时,则在 T 的左子树査找。

  4. 第 32〜35 行,递归调用本函数,直到找到则返回 false ,否则说明插入结点成功,执行下面语句。

  5. 第 36〜53 行,当 taller 为 TRUE 时,说明插入了结点,此时需要判断 T 的平衡因子,如果是 1 ,说明左子树高于右子树,需要调用 LeftBalance 函数进行左平衡旋转处理。如果为 0 或 -1 ,则说明新插入结点没有让整棵二叉排序树失去平衡性,只需要修改相关的 BF 值即可。

  6. 第 55〜80 行,说明新结点 e 大于 T 的根结点的值,在 T 的右子树查找。代码上述类似,不再详述。

对于这段代码来说,我们只需要在需要构建平衡二叉树的时候执行如下列代码即可在内存中生成一棵与图 8-7-4 的图 2 相同的平衡的二叉树。

int i;
int a[10] = { 3, 2, 1, 4, 5, 6, 7, 10, 9, 8 };
BiTree T = NULL;
Status taller;
for (i = 0; i<10; i++)
{InsertAVL(&T, a[i], &taller);
}

不容易,终于讲完了,本算法代码很长,是有些复杂,编程中容易在很多细节上出错,要想真正掌握它,需要多练习。不过其思想还是不难理解的,总之就是把不平衡消灭在最早时刻。

如果我们需要查找的集合本身没有顺序,在频繁查找的同时也需要经常的插入和删除操作,显然我们需要构建一棵二叉排序树,但是不平衡的二叉排序树,查找效率是非常低的,因此我们需要在构建时,就让这棵二叉排序树是平衡二叉树,此时我们的查找时间复杂度就为 O(logn) ,而插入和删除也为 O(logn) 。这显然是比较理想的一种动态查找表算法。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 可不就是平凡的世界

    无意间刷到了《平凡的世界》电视剧,虽然依旧觉得毁原著,可又不想无聊致死,不想依旧被感染至此,唉!不知道以后的我再看这篇时会不会忆起现在的心情呢。《囚徒》 普希金 我坐在阴湿牢狱的铁栏后 一只在禁锢中成长的鹰雏 和我郁郁地做伴;它扑着翅膀, 在铁窗下啄食着血腥的食…...

    2024/4/14 13:21:41
  2. 莫使时光太匆匆

    早晨,地铁上。 虽是一如既往地挤,一如既往地嘈杂,但这次并没有像往常一样闭上眼睛,以此来抵挡等待的痛苦。因为忽然发现一件有趣的事情。 相信很多人都有这样选择的经历,即一段时间内只做一件事,比如为了准备期末考试,会放弃读很多想读的书。这看似很合理,得一物于桑榆…...

    2024/4/19 4:05:51
  3. J2EE面试题

    1、面向对象的特征有哪些方面 1. 抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。2.继承: 继承是一…...

    2024/4/14 13:21:47
  4. Tensorflow2.0 医学图像分割(大脑肿瘤识别)

    医学图像分割是医学图像处理与分析领域的复杂而关键的步骤,其目的是将医学图像中具有某些特殊含义的部分分割出来,并提取相关特征,为临床诊疗和病理学研究提供可靠的依据,辅助医生作出更为准确的诊断。本次实验使用大脑肿瘤数据集,经过网络训练之后可以将大脑CT图像中的肿…...

    2024/4/18 10:07:58
  5. 浅谈分布式存储架构: IPFS和HDFS

    分布式存储架构是一个复杂的系统工程,针对特定应用的数据存储有不同的系统架构解决方案。不同的存储方法会影响存储性能、存储成本、冗余度、工程复杂性等。分布式存储的历史分布式存储最早是由谷歌提出的,其目的是通过廉价的服务器来解决大规模,高并发场景下的 Web 访问问题…...

    2024/4/15 13:13:22
  6. 原地合并两个有序数组

    LeetCode 88. 合并两个有序数组 给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。 说明: 初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元…...

    2024/4/15 16:51:31
  7. bash的-c选项

    关于bash的-c选项 bash的-c选项, 表示把后续的参数当做命令行, 而不是脚本. manual page中, 关于bash的synopsis是这样的: [gewkiff@fedora d2]$ man -f bash bash (1) - GNU Bourne-Again SHell 然后执行 man 1 bash, 显示如下 可以看到, 它的SYNOPSIS是 bash […...

    2024/4/14 13:21:26
  8. 前后端数据交互如何避免中文乱码问题??(亲自踩坑)

    文章目录事件起因:1.设置Tomcat的servlet.xml的编码方式2.配置编码过滤器3.在JSP页面或者HTML页面中设置编码4.在请求中具体指定 事件起因: 我在页面中要实现一个模糊查询,我用参数的序列化然后把参数回传到后端查询,一直显示无数据,一看日志文件才发现:传过来的参数(作为查询的…...

    2024/4/18 17:48:54
  9. 牛牛学圆

    链接:https://ac.nowcoder.com/acm/problem/21997 来源:牛客网 题目描述 :已知圆的半径,求它的周长和面积。此题令pi=3.14159 输入描述:输入一个实数a 输出描述:输出两行,每行一个实数,第一行表示周长,第二行表示面积(结果均保留六位小数) 示例1 输入 4 输出 25.13272…...

    2024/4/14 13:21:56
  10. Goland:Unresolved reference ‘NewFunction‘

    Goland:Unresolved reference ‘NewFunction’ (一)描述 在给Goland升级版本后,所有包的引用都提示Unresolved reference ‘方法名’。 (二)原因 之前的项目中的.idea文件夹是旧版本的Goland创建的,里面应该是些数据和新版本不兼容。 (三)解决方法 将项目中的.idea文件…...

    2024/4/14 13:21:36
  11. Typora 博文标题自动编号

    Typora 博文标题自动编号 1、Why? 1.1、Typora标题自动编号修改 base.user.css 中的 css 代码可达到如下效果,看着还不错1.2、博文效果修改 base.user.css 中的 css 代码只能实现 Typora 中的视觉效果,并不是真正在标题中添加了序号2、Let’s Do it 2.1、目标编写 Java 脚本…...

    2024/4/20 12:15:38
  12. HTML-块元素与行内元素

    块元素: 作用: 搭建网页结构 特点: 1) 独占一行空间 2) 默认宽度为100% 3) 高度由子元素或内容决定 4) 可以通过css指定其宽度 标签: div html body h1-h6 p ul>li ol>li dl>dt,dd article 行内元素: 作用:填充 特点: 与其他行内元素共享一行空间 不能通过css为…...

    2024/4/1 4:01:10
  13. Spring相关问题汇总

    1.Spring中Bean的生命周期是怎样的?...

    2024/4/20 2:04:58
  14. [LeetCode]400. 第N个数字

    题目 在无限的整数序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …中找到第 n 个数字。 注意: n 是正数且在32位整数范围内 ( n < 2^31)。 示例 1: 输入: 3输出: 3示例 2: 输入: 11输出: 0说明: 第11个数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是0,它是10的一部分…...

    2024/4/18 18:56:25
  15. 剑指 Offer 07. 重建二叉树

    这道题我觉得吧经典,并且因为基础不牢的缘故,我一年内做了两三次但都还是没有记住方法,这次想仔细分析其中的步骤,希望下次遇到不会再去看答案。。。。代码如下: /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* …...

    2024/4/14 13:21:21
  16. 目标检测(一):边界框、锚框、多尺度目标检测

    本文参考–PyTorch官方教程中文版链接:http://pytorch123.com/FirstSection/PyTorchIntro/ Pytorch中文文档:https://pytorch-cn.readthedocs.io/zh/latest/package_references/Tensor/ PyTorch英文文档:https://pytorch.org/docs/stable/tensors.html 《深度学习之PyTorch物…...

    2024/4/14 13:21:41
  17. Codeforces Round #632 (Div. 2) C. Eugene and an array 题解(前缀和+思维)

    题目链接 题目大意 求判定为“good”的子区间个数。good : 在该区间内的所有子区间,不存在和为0的子区间。子序列:对原序列首位依次删除任意个形成的序列 题目思路 这个题目很巧妙,首先肯定是要用前缀和,如果pre[i]和pre[j]相等,那么[i+1,j]的和为0。这个题目最巧妙的是求…...

    2024/4/14 13:21:31
  18. html2canvas实现页面截屏功能

    html2canvas实现页面截屏功能 原理是将需要生成截屏的HTML结构写入Canvas里面,利用Canvas生成页面截图,在浏览器不支持Canvas的情况下,将采用Flashcanvas或ExplorerCanvas技术代替实现//以vue为例let that = this;//由于业务需求是进入页面就要生成截图 所以利用setTimeOut…...

    2024/4/16 18:50:18
  19. spring boot整合Swagger2的示例代码

    摘要:这篇Java开发技术栏目下的“spring boot整合Swagger2的示例代码”,介绍的技术点是“Spring Boot、Swagger2、Spring、示例代码、示例、代码”,希望对大家开发技术学习和问题解决有帮助。Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的 We…...

    2024/4/15 16:51:01
  20. 在Linux下使用R语言

    在Windows下使用R语言相当简单,因为有安装之后直接是图形界面(GUI)的安装程序,各类常用操作可以在GUI下完成,包括R官方说明在Unix-alike下使用的各种命令比如getCRANmirrors()或者chooseCRANmirror()这类。但Linux下就没这么好命,当然Linux也主要是给程序猿/媛和攻城…...

    2024/4/16 16:20:22

最新文章

  1. 【网络设备巡检命令】--思科、华为、H3C、锐捷

    【网络设备巡检命令】--思科、华为、H3C、锐捷 一、思科二、华为三、H3C四、锐捷 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 一、思科 1、查看系统信息&#xff1a; show version2、查看时间&#xff1a; show clock3、查看序列号&a…...

    2024/4/20 21:03:13
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 《c++》多态案例一.电脑组装

    一.代码展示 #include <iostream> using namespace std; class CPU { public://抽象计算函数virtual void calculate() 0;};class CVideoCard { public://抽象显示函数virtual void display() 0;}; class Memory { public://抽象存储函数virtual void storage() 0;};…...

    2024/4/19 7:49:33
  4. Vue3学习笔记+报错记录

    文章目录 1.创建Vue3.0工程1.1使用vue-cli创建1.2 使用vite创建工程1.3.分析Vue3工程结构 2.常用Composition2.1 拉开序幕的setup2.2 ref函数_处理基本类型2.3 ref函数_处理对象类型2.4 ref函数使用总结 1.创建Vue3.0工程 1.1使用vue-cli创建 查看vue/cli版本&#xff0c;确保…...

    2024/4/16 23:49:52
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/19 14:24:02
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/19 18:20:22
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/19 11:57:31
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/19 11:57:31
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/19 11:57:52
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/19 11:57:53
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/19 11:58:14
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/19 11:58:20
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/20 7:40:48
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/19 11:58:39
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/19 11:58:51
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/20 3:12:02
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/19 11:59:15
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/19 11:59:23
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/19 11:59:44
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/19 11:59:48
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/19 12:00:06
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/19 16:57:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/19 12:00:25
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/19 12:00:40
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57