7.6.平衡二叉樹(英文縮寫為AVL樹)


一.平衡二叉樹的定義:

1.平衡二叉樹簡稱平衡樹(AVL樹,該縮寫來源于平衡二叉樹的發明人的名字簡稱);

2.結點的平衡因子=左子樹高-右子樹高;

3.以上述圖片左下角的二叉樹為例,結點50的左子樹的高度為2,右子樹的高度為3,因此結點50的平衡因子為2-3即-1;

4.顯然如果一棵二叉樹是平衡的,那么各個結點的平衡因子只可能是-1、0、1,也就是絕對值不超過1,如果二叉樹中有任何一個結點的平衡因子絕對值超過1,那么這棵二叉樹一定不是平衡二叉樹;

5.在平衡二叉樹結點的結構體中可以新增一個參數int balance記錄平衡因子,如下:

#include<stdio.h>
?
//平衡二叉樹結點
typedef struct AVLNode
{int key; ? ? ?//結點的數據域,該變量的類型不固定,因題而異int balance; ?//平衡因子struct AVLNode *lchild,*rchild; //結點的左孩子指針、右孩子指針 ?
}AVLNode,*AVLTree; //AVLNode代表平衡二叉樹的結點,*AVLTree代表平衡二叉樹 
?
int main()
{return 0;
}

6.之前說過,如果使一棵二叉排序樹保持平衡,就可以保證這棵二叉排序樹的查找效率達到O(log?n)即查找效率達到最好,因此要重點研究在插入一個新結點之后,如何保持二叉樹的平衡。


二.平衡二叉樹的插入:

實例:

以上述圖片左邊的二叉排序樹為例,

現在插入關鍵字為67的結點,根據二叉排序樹的特性可得知插入的具體位置在關鍵字為68的結點的左子樹上,

新插入關鍵字為67的結點的所有祖先的平衡因子都受到了影響,

現在要讓二叉排序樹中每一個結點恢復平衡的方法就是可以從新插入的結點開始往上找,找到第一個不平衡的結點

->本例中從關鍵字為67的結點想上找第一個不平衡的結點是關鍵字為70的結點,該結點的平衡因子為2,它是距離新插入的結點67第一個不平衡的結點,現在可以把以關鍵字為70的結點作為根結點的子樹稱為"最小不平衡子樹",之所以稱為最小,是因為如果繼續往上找,第二個不平衡的結點是關鍵字為66的結點,以這個結點為根結點的子樹顯然要更大,實際中只需要調整這棵"最小不平衡子樹"即可。

調整的效果如下圖:

具體的調整規則之后探討,只需要知道把這棵"最小不平衡子樹"恢復平衡之后,其他的祖先結點就都恢復了平衡,

所以當插入一個新結點之后導致不平衡的話,只需要調整"最小不平衡子樹"就可以讓其他結點恢復平衡。


三.調整"最小不平衡子樹"->LL和RR:

分為四種情況,分別是LL、RR、LR、RL:

1.LL:在A結點的左孩子的左子樹中插入新結點導致A結點不平衡->需要右旋

以上述圖片為例,

  • 灰色方形的框表示結點的子樹,該子樹的高度用H表示,其中這些子樹都是平衡的

  • BL表示B結點的左子樹,BR表示B結點的右子樹,AR表示A結點的右子樹

最左邊的二叉樹中A結點的左子樹是以B結點為根結點的樹,其中BL的高度為H,BR的高度也為H,算上B結點,根據二叉樹的定義可知以B結點為根結點的樹的高度為H+1(加的1是B結點的高度),A結點的右子樹是AR,高度為H,

所以A結點的平衡因子=(H+1)-H=1,所以A結點是平衡的;B結點的平衡因子=H-H=0,所以B結點是平衡的;

此時在A結點的左孩子即B結點的左子樹BL中插入一個新結點(上述圖片中間的二叉樹),會導致A結點不平衡,這是因為B結點的左子樹BL變高了,BL的高度變為了H+1,所以A結點的左子樹整體來看高度變為了H+2,而A結點的右子樹AR的高度仍保持為H,所以此時A結點的平衡因子=(H+2)-H=2,導致A結點不平衡;B結點的平衡因子=(H+1)-H=1,所以B結點是平衡的,

(注:假定以A結點為根結點的二叉樹就是最小不平衡子樹)

因此需要調整以A結點為根結點的二叉樹(即上述圖片中最中間的二叉樹)使其保持平衡,

如下圖:

如上圖,

要調整以A結點為根結點的二叉樹即"最小不平衡子樹"(即上述圖片中最中間的二叉樹)使其平衡,

調整的結果需要滿足:

  1. 恢復"最小不平衡子樹"的平衡

  2. 使得"最小不平衡子樹"在調整之后依然滿足二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值"

在本例中結點的大小關系為BL<B<BR<A<AR(注:以A結點為根結點的二叉樹是二叉排序樹,在A結點的左子樹中的每一個結點的值都小于結點A的值,比如BR<A,B<A),

使得以A結點為根結點的二叉樹即"最小不平衡子樹"恢復平衡的處理方法如下:

步驟一:讓B結點右旋->具體的做法就是讓B結點向右上旋轉代替A結點成為該二叉樹的根結點,B結點的右子樹就是以A結點為根結點的樹;

步驟二:處理子樹BL、BR、AR->

  • 首先看子樹BL,BL之前是B結點的左子樹,BL的值小于B結點值(BL<B),所以只能把BL連接在B結點的左子樹,因為要保證"左子樹結點值<根結點值<右子樹結點值"

  • 再看子樹BR,BR之前是B結點的右子樹,現在B結點的右子樹已經掛了A結點,那么BR就不能作為B結點的右子樹了,但是有BR的值小于A結點的值(BR<A),所以可以把子樹BR當作A結點的左子樹

  • 最后看子樹AR,AR之前是A結點的右子樹,有AR的值大于A結點的值(A<AR),所以AR繼續作為A結點的右子樹

這樣就可以既保證二叉排序樹的特性,同時BL這個部分的高度是H+1即成功插入了新結點,

經過上述的調整之后(上述圖片最右邊的樹)B結點的左子樹BL的高度為H+1、右子樹的高度為H+1,即B結點的平衡因子=(H+1)-(H+1)=0,

A結點的左子樹BR的高度為H、右子樹AR的高度為H,即A結點的平衡因子=H-H=0,

可知以A結點為根結點的子樹和以B結點為根結點的子樹都保持了平衡,

這樣一來就可以讓"最小不平衡子樹"恢復平衡,同時又保持二叉排序樹的特性。

Ⅰ.思考1:

為什么要假定所有灰色方形的框表示的子樹的高度都是H呢,那有沒有其他的情況?

首先看上述圖片中最左邊的樹的AR,A結點的右子樹AR假設高度為H,如果AR高度改為H+1,由于A結點的左子樹的高度也為H+1,所以此時A結點的平衡因子=(H+1)-(H+1)=0,A結點是平衡的

這種情況下在BL插入一個新結點,BL的高度變為H+1,所以A結點左子樹的高度為H+2,A結點的右子樹的高度為H+1,那么A結點平衡因子=(H+2)-(H+1)=1,此時A結點是平衡的,就不會出現所需要探討的不平衡的情況,所以A結點右子樹的高度一定是H,而不是H+1。

Ⅱ.思考2:

為什么要假定所有灰色方形的框表示的子樹的高度都是H呢,那有沒有其他的情況?

首先看上述圖片中最左邊的樹的AR,A結點的右子樹AR假設高度為H,如果AR高度改為H-1,由于A結點的左子樹的高度為H+1,所以此時A結點的平衡因子=(H+1)-(H-1)=2,使得A結點一開始就是不平衡的,而現在要探討的是插入一個新結點后才導致A結點不平衡,與題目要求違背了。

Ⅲ.思考3:

為什么要假定所有灰色方形的框表示的子樹的高度都是H呢,那有沒有其他的情況?

首先看上述圖片中最左邊的樹的BR,B結點的右子樹BR假設高度為H,如果BR高度改為H-1,由于B結點的左子樹BL的高度為H,所以此時B結點的平衡因子=H-(H-1)=1,可知B結點是平衡的,滿足平衡二叉樹的條件,

但是在這種情況下,如果B結點的左子樹BL添加一個結點后高度變為H+1,這時B結點的平衡因子=(H+1)-(H-1)=2,導致B結點不平衡,這樣的話B結點就是距離新插入的結點最近的不平衡點,所以以B結點為根結點的樹就是"最小不平衡子樹"了,但現在研究的是以A結點為根結點的樹是"最小不平衡子樹",所以B結點的右子樹BR的高度不可能是H-1,而是H->其他的情況同理,自行推理。

總之,在這個地方只要假定某一個灰色方形的框表示的子樹的高度是H的話,那其他的灰色方形的框表示的子樹的高度也必須是H,只有這樣才能在LL處插入新結點后導致A結點是為"最小不平衡子樹"的根結點。

2.LL的代碼實現:

以上述圖片中的二叉排序樹為例,

  • f指針(father的縮寫)指向A結點即f指針表示A結點;A結點的左子樹為f->lchild;A結點的右子樹為f->rchild(注:f指針始終指向A結點,不會改變)

  • p指針指向B結點即p指針表示B結點;B結點的左子樹為p->lchild;B結點的右子樹為p->rchild(注:p指針始終指向B結點,不會改變)

  • gf指針(grandfather的縮寫)指向整個二叉樹的根結點的父結點;由于整個二叉樹的根結點可能是其父結點的左孩子,也可能是右孩子,所以整個二叉樹的根結點既可能是gf->lchild,也可能是gf->rchild,因此gf->lchild或gf->rchild就表示整個二叉樹的根結點(注:整個二叉樹的根結點未必是A結點,也可能是B結點)

根據之前的分析,要讓LL的情況恢復平衡,需要B結點右旋,旋轉的結果就是新的二叉樹,其中->

  • 根結點從A結點變為B結點

  • A結點的左子樹從以B結點為根結點的樹變為BR,A結點的右子樹AR沒變

  • B結點的左子樹BL沒變,B結點的右子樹從BR變為以A結點為根結點的樹

各個結點的子樹情況二叉樹未"右旋"時二叉樹"右旋"后
整棵二叉樹的根結點即gf->lchild或gf->rchildgf->lchild或gf->rchild的值為A結點即fgf->lchild或gf->rchild的值為B結點即p
A結點的左子樹即f->lchildf->lchild是以B結點為根結點的子樹即pf->lchild是子樹BR
A結點的右子樹即f->rchildf->rchild是子樹ARf->rchild是子樹AR
B結點的左子樹即p->lchildp->lchild是子樹BLp->lchild是子樹BL
B結點的右子樹即p->rchildp->rchild是子樹BRp->rchild是以A結點為根結點的子樹即f

對于代碼的書寫只需要針對發生改變的子樹和結點即可,還需要注意其中的邏輯(代碼不唯一):

步驟一:對于A結點,由于A結點只有左子樹f->lchild發生了改變即從以B結點為根結點的子樹p變為子樹BR,所以可以是f->lchild = p->rchild;

步驟二:對于B結點,由于B結點只有右子樹p->rchild發生了改變即從子樹BR變為以A結點為根結點的子樹f,所以可以是p->rchild = f;

步驟三:對于整棵二叉樹,只有根結點發生了改變即從A結點f變為B結點p,所以可以是gf->lchild = p或gf->rchild = p;,

這樣就可以實現"右旋"操作,同時可以保證這棵二叉樹依然保持二叉排序樹的特性。

3.RR:在A結點的右孩子的右子樹中插入新結點導致A結點不平衡->需要左旋

以上述圖片為例,

  • 灰色方形的框表示結點的子樹,該子樹的高度用H表示,其中這些子樹都是平衡的

  • BL表示B結點的左子樹,BR表示B結點的右子樹,AL表示A結點的左子樹

(本例中假設在插入新結點之后以A結點為根結點的子樹是"最小不平衡子樹",且AL、BL、BR這三個部分的高度最開始必須都是相同的,原理同"LL里的思考")

上述圖片中最左邊的二叉樹中A結點的右子樹是以B結點為根結點的樹,其中BL的高度為H,BR的高度也為H,算上B結點,根據二叉樹的定義可知以B結點為根結點的樹的高度為H+1(加的1是B結點的高度),A結點的左子樹是AL,高度為H,

所以A結點的平衡因子=H-(H+1)=-1,所以A結點是平衡的;B結點的平衡因子=H-H=0,所以B結點是平衡的,

此時在A結點的右孩子即B結點的右子樹BR中插入一個新結點(上述圖片中間的二叉樹),會導致A結點不平衡,這是因為B結點的右子樹BR變高了,BR的高度變為了H+1,所以A結點的右子樹整體來看高度變為了H+2,而A結點的左子樹AL的高度仍保持為H,所以此時A結點的平衡因子=H-(H+2)=-2,導致A結點不平衡;B結點的平衡因子=H-(H+1)=-1,所以B結點是平衡的,

(注:假定以A結點為根結點的二叉樹就是最小不平衡子樹)

因此需要調整以A結點為根結點的二叉樹(即上述圖片中最中間的二叉樹)使其保持平衡,

如下圖:

如上圖,

要調整以A結點為根結點的二叉樹即"最小不平衡子樹"(即上述圖片中最中間的二叉樹)使其平衡,

調整的結果需要滿足:

  1. 恢復"最小不平衡子樹"的平衡

  2. 使得"最小不平衡子樹"在調整之后依然滿足二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值"

在本例中結點的大小關系為AL<A<BL<B<BR(注:以A結點為根結點的二叉樹是二叉排序樹,在A結點的右子樹中的每一個結點的值都大于結點A的值,比如BL>A,B>A),

使得以A結點為根結點的二叉樹即"最小不平衡子樹"恢復平衡的處理方法如下:

步驟一:讓B結點左旋->具體的做法就是讓B結點向左上旋轉代替A結點成為該二叉樹的根結點,B結點的左子樹就是以A結點為根結點的樹;

步驟二:處理子樹AL、BL、BR->

  • 首先看子樹BR,BR之前是B結點的右子樹,BR的值大于B結點值(BR>B),所以只能把BR連接在B結點的右子樹,因為要保證"左子樹結點值<根結點值<右子樹結點值"

  • 再看子樹AL,AL之前是A結點的左子樹,有AL的值小于A結點的值(AL<A),所以AL必須作為A結點的左子樹

  • 最后看子樹BL,BL之前是B結點的左子樹,現在B結點的左子樹已經掛了A結點,那么BL就不能作為B結點的左子樹了,但是有BL的值大于A結點的值且小于B結點的值(B>BL>A),所以可以把子樹BL當作A結點的右子樹(BL在B結點的左子樹中)

這樣就可以既保證二叉排序樹的特性,同時BR這個部分的高度是H+1即成功插入了新結點,

經過上述的調整之后(上述圖片最右邊的樹)B結點的左子樹的高度為H+1、右子樹BR的高度為H+1,即B結點的平衡因子=(H+1)-(H+1)=0,

A結點的左子樹AL的高度為H、右子樹BL的高度為H,即A結點的平衡因子=H-H=0,

可知以A結點為根結點的子樹和以B結點為根結點的子樹都保持了平衡,

這樣一來就可以讓"最小不平衡子樹"恢復平衡,同時又保持二叉排序樹的特性。

4.RR的代碼實現:

以上述圖片中的二叉排序樹為例,

  • f指針(father的縮寫)指向A結點即f指針表示A結點;A結點的左子樹為f->lchild;A結點的右子樹為f->rchild(注:f指針始終指向A結點,不會改變)

  • p指針指向B結點即p指針表示B結點;B結點的左子樹為p->lchild;B結點的右子樹為p->rchild(注:p指針始終指向B結點,不會改變)

  • gf指針(grandfather的縮寫)指向整個二叉樹的根結點的父結點;由于整個二叉樹的根結點可能是其父結點的左孩子,也可能是右孩子,所以整個二叉樹的根結點既可能是gf->lchild,也可能是gf->rchild,因此gf->lchild或gf->rchild就表示整個二叉樹的根結點(注:整個二叉樹的根結點未必是A結點,也可能是B結點)

根據之前的分析,要讓RR的情況恢復平衡,需要B結點左旋,旋轉的結果就是新的二叉樹,其中->

  • 根結點從A結點變為B結點

  • A結點的左子樹AL沒變,A結點的右子樹從以B結點為根結點的樹變為BL

  • B結點的左子樹從BL變為以A結點為根結點的樹,B結點的右子樹BR沒變

各個結點的子樹情況二叉樹未"右旋"時二叉樹"右旋"后
整棵二叉樹的根結點即gf->lchild或gf->rchildgf->lchild或gf->rchild的值為A結點即fgf->lchild或gf->rchild的值為B結點即p
A結點的左子樹即f->lchildf->lchild是子樹ALf->lchild是子樹AL
A結點的右子樹即f->rchildf->rchild是以B結點為根結點的子樹即pf->rchild是子樹BL
B結點的左子樹即p->lchildp->lchild是子樹BLp->lchild是以A結點為根結點的子樹即f
B結點的右子樹即p->rchildp->rchild是子樹BRp->rchild是子樹BR

對于代碼的書寫只需要針對發生改變的子樹和結點即可,還需要注意其中的邏輯(代碼不唯一):

步驟一:對于A結點,由于A結點只有右子樹f->rchild發生了改變即從以B結點為根結點的子樹p變為子樹BL,所以可以是f->rchild = p->lchild;

步驟二:對于B結點,由于B結點只有左子樹p->lchild發生了改變即從子樹BL變為以A結點為根結點的子樹f,所以可以是p->lchild = f;

步驟三:對于整棵二叉樹,只有根結點發生了改變即從A結點f變為B結點p,所以可以是gf->lchild = p或gf->rchild = p;,

這樣就可以實現"左旋"操作,同時可以保證這棵二叉樹依然保持二叉排序樹的特性。


四.調整"最小不平衡子樹"->LR和RL:(代碼類似LL和RR,自行推理即可)

1.LR:在A結點的左孩子的右子樹中插入新結點導致A結點不平衡

以上述圖片為例,

  • 灰色方形的框表示結點的子樹,該子樹的高度用H表示,其中這些子樹都是平衡的

  • BL表示B結點的左子樹,BR表示B結點的右子樹,AR表示A結點的右子樹

(本例中假設在插入新結點之后以A結點為根結點的子樹是"最小不平衡子樹",且AR、BL、BR這三個部分的高度最開始必須都是相同的,原理同"LL里的思考")

上述圖片中最左邊的二叉樹中A結點的左子樹是以B結點為根結點的樹,其中BL的高度為H,BR的高度也為H,算上B結點,根據二叉樹的定義可知以B結點為根結點的樹的高度為H+1(加的1是B結點的高度),A結點的右子樹是AR,高度為H,

所以A結點的平衡因子=(H+1)-H=1,所以A結點是平衡的;B結點的平衡因子=H-H=0,所以B結點是平衡的,

此時在A結點的左孩子即B結點的右子樹BR(上述圖片打錯了)中插入一個新結點(上述圖片中間的二叉樹),會導致A結點不平衡,這是因為B結點的右子樹BR變高了,BR的高度變為了H+1,所以A結點的左子樹整體來看高度變為了H+2,而A結點的右子樹AR的高度仍保持為H,所以此時A結點的平衡因子=(H+2)-H=2,導致A結點不平衡;B結點的平衡因子=H-(H+1)=-1,所以B結點是平衡的,

(注:假定以A結點為根結點的二叉樹就是最小不平衡子樹)

因此需要調整以A結點為根結點的二叉樹使其保持平衡->為了方便探討,需要把B結點的右子樹BR展開,

如下圖:

如上圖,

現在把B結點的右子樹BR展開,

假設子樹BR是以C結點為根結點的二叉樹,C結點的左子樹為CL,C結點的右子樹為CR,

最開始在上述圖片最左邊的二叉樹中由于子樹BR的高度為H,所以子樹CL、CR的高度都為H-1(CL、CR的高度最開始必須是相同的,原理同"LL里的思考")->其中A結點的平衡因子=(H+1)-H=1即A結點是平衡的;B結點的平衡因子=H-H=0即B結點是平衡的;C結點的平衡因子=(H-1)-(H-1)=0即C結點是平衡的;

現在在子樹BR中插入新結點之后(上述圖片最右邊的二叉樹),子樹BR的高度變為H+1,這里可以假設把新結點插在了C結點的右子樹CR,導致子樹CR的高度變為了H(新結點也可以插在了C結點的左子樹CL,導致子樹CL的高度變為了H,無論是哪種情況,最終的處理方法都是一樣的,這里先假定插入的新結點在子樹CR上)->其中A結點的平衡因子=(H+2)-H=2即A結點是不平衡的;B結點的平衡因子=H-(H+1)=-1即B結點是平衡的;C結點的平衡因子=(H-1)-H=-1即C結點是平衡的;

使得"最小不平衡子樹"即以A結點為根結點的子樹(上述圖片最右邊的二叉樹)恢復平衡的處理方法如下圖:

如上圖:

要讓"最小不平衡子樹"即以A結點為根結點的子樹(上述圖片最右邊的二叉樹)恢復平衡,

核心就是讓該"最小不平衡子樹"中的C結點先"左旋",讓C結點頂替B結點的位置,再讓C結點"右旋",讓C結點頂替A結點的位置,

其中結點的大小關系為BL<B<CL<C<CR<A<AR(注:以A結點為根結點的二叉樹是二叉排序樹,在A結點的左子樹中的每一個結點的值都小于結點A的值,比如CL<A,CR<A;以B結點為根結點的二叉樹也是二叉排序樹,在B結點的右子樹中的每一個結點的值都大于結點B的值,比如B<C,B<CL,B<CR),

具體操作如下圖:

如上圖,

要調整以A結點為根結點的二叉樹即"最小不平衡子樹"使其平衡,

調整的結果需要滿足:

  1. 恢復"最小不平衡子樹"的平衡

  2. 使得"最小不平衡子樹"在調整之后依然滿足二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值"

在本例中結點的大小關系為BL<B<CL<C<CR<A<AR,

使得以A結點為根結點的二叉樹即"最小不平衡子樹"恢復平衡的處理方法如下:

步驟一:讓C結點左旋->具體的做法就是讓C結點向左上旋轉代替B結點,C結點的左子樹就是以B結點為根結點的樹;

步驟二:處理子樹BL、CL、CR、AR->

  • 首先看子樹BL,BL之前是B結點的左子樹,BL的值小于B結點值(BL<B),所以只能把BL連接在B結點的左子樹,因為要保證"左子樹結點值<根結點值<右子樹結點值"

  • 再看子樹CL,CL之前是C結點的左子樹,現在C結點的左子樹已經掛了B結點,那么CL就不能作為C結點的左子樹了,但是有CL的值大于B結點的值(B<CL),所以可以把子樹CL當作B結點的右子樹

  • 再看子樹CR,CR之前是C結點的右子樹,有CR的值大于C結點的值(C<CR),所以CR繼續作為C結點的右子樹

  • 最后看子樹AR,AR之前是A結點的右子樹,有AR的值大于A結點的值(A<AR),所以AR繼續作為A結點的右子樹

此時得到了上述圖片中最中間的二叉樹->其中A結點的平衡因子=(H+2)-H=2即A結點是不平衡的;B結點的平衡因子=H-(H-1)=1即B結點是平衡的;C結點的平衡因子=(H+1)-H=1即C結點是平衡的,只有A結點不平衡,所以繼續調整使得以A結點為根結點的二叉樹保持平衡,

步驟三:(上述圖片中最中間的二叉樹)讓C結點右旋->具體的做法就是讓C結點向右上旋轉代替A結點,C結點的右子樹就是以A結點為根結點的樹;

步驟四:處理子樹BL、CL、CR、AR->

  • 首先看子樹BL,BL之前是B結點的左子樹,BL的值小于B結點值(BL<B),所以只能把BL連接在B結點的左子樹,因為要保證"左子樹結點值<根結點值<右子樹結點值"

  • 再看子樹CL,CL之前是B結點的右子樹,有CL的值大于B結點的值(B<CL),所以CL繼續作為B結點的右子樹

  • 再看子樹CR,CR之前是C結點的右子樹,現在C結點的右子樹已經掛了A結點,那么CR就不能作為C結點的右子樹了,但是有CR的值小于A結點的值(CR<A),所以可以把子樹CR當作A結點的左子樹

  • 最后看子樹AR,AR之前是A結點的右子樹,有AR的值大于A結點的值(A<AR),所以AR繼續作為A結點的右子樹

這樣就可以既保證二叉排序樹的特性,同時BR這個部分的高度是H+1即成功插入了新結點,

經過上述的調整之后(上述圖片最右邊的樹)B結點的左子樹BL的高度為H、右子樹CL的高度為H-1,即B結點的平衡因子=H-(H-1)=1,

A結點的左子樹CR的高度為H、右子樹AR的高度為H,即A結點的平衡因子=H-H=0,

C結點的左子樹的高度為H+1、右子樹的高度為H+1,即C結點的平衡因子=(H+1)-(H+1)=0,

可知以A結點為根結點的子樹、以B結點為根結點的子樹和以C結點為根結點的子樹都保持了平衡,

這樣一來就可以讓"最小不平衡子樹"恢復平衡,同時又保持二叉排序樹的特性。

注意:

如上圖,

本例假定插入的新結點在子樹CR上,

實際上也有可能是插入在子樹CL上,這種情況的處理方式同子樹CL,

也可以保證使所有的結點都恢復平衡。

2.RL:在A結點的右孩子的左子樹中插入新結點導致A結點不平衡

以上述圖片為例,

  • 灰色方形的框表示結點的子樹,該子樹的高度用H表示,其中這些子樹都是平衡的

  • BL表示B結點的左子樹,BR表示B結點的右子樹,AL表示A結點的左子樹

(本例中假設在插入新結點之后以A結點為根結點的子樹是"最小不平衡子樹",且AL、BL、BR這三個部分的高度最開始必須都是相同的,原理同"LL里的思考")

上述圖片中最左邊的二叉樹中A結點的右子樹是以B結點為根結點的樹,其中BL的高度為H,BR的高度也為H,算上B結點,根據二叉樹的定義可知以B結點為根結點的樹的高度為H+1(加的1是B結點的高度),A結點的左子樹是AL,高度為H,

所以A結點的平衡因子=H-(H+1)=-1,所以A結點是平衡的;B結點的平衡因子=H-H=0,所以B結點是平衡的,

此時在A結點的右孩子即B結點的左子樹BL中插入一個新結點(上述圖片中間的二叉樹),會導致A結點不平衡,這是因為B結點的左子樹BL變高了,BL的高度變為了H+1,所以A結點的右子樹整體來看高度變為了H+2,而A結點的左子樹AL的高度仍保持為H,所以此時A結點的平衡因子=H-(H+2)=-2,導致A結點不平衡;B結點的平衡因子=(H+1)-H=1,所以B結點是平衡的,

(注:假定以A結點為根結點的二叉樹就是最小不平衡子樹)

因此需要調整以A結點為根結點的二叉樹使其保持平衡->為了方便探討,需要把B結點的左子樹BL展開,

如下圖:

如上圖,

現在把B結點的左子樹BL展開,

假設子樹BL是以C結點為根結點的二叉樹,C結點的左子樹為CL,C結點的右子樹為CR,

最開始在上述圖片最左邊的二叉樹中由于子樹BL的高度為H,所以子樹CL、CR的高度都為H-1(CL、CR的高度最開始必須是相同的,原理同"LL里的思考")->其中A結點的平衡因子=H-(H+1)=-1即A結點是平衡的;B結點的平衡因子=H-H=0即B結點是平衡的;C結點的平衡因子=(H-1)-(H-1)=0即C結點是平衡的;

現在在子樹BL中插入新結點之后(上述圖片最右邊的二叉樹),子樹BL的高度變為H+1,這里可以假設把新結點插在了C結點的左子樹CL,導致子樹CL的高度變為了H(新結點也可以插在了C結點的右子樹CR,導致子樹CR的高度變為了H,無論是哪種情況,最終的處理方法都是一樣的,這里先假定插入的新結點在子樹CL上)->其中A結點的平衡因子=H-(H+2)=-2即A結點是不平衡的;B結點的平衡因子=(H+1)-H=1即B結點是平衡的;C結點的平衡因子=H-(H-1)=1即C結點是平衡的;

使得"最小不平衡子樹"即以A結點為根結點的子樹(上述圖片最右邊的二叉樹)恢復平衡的處理方法如下圖:

如上圖:

要讓"最小不平衡子樹"即以A結點為根結點的子樹(上述圖片最右邊的二叉樹)恢復平衡,

核心就是讓該"最小不平衡子樹"中的C結點先"右旋",讓C結點頂替B結點的位置,再讓C結點"左旋",讓C結點頂替A結點的位置,

其中結點的大小關系為AL<A<CL<C<CR<B<BR(注:以A結點為根結點的二叉樹是二叉排序樹,在A結點的右子樹中的每一個結點的值都大于結點A的值,比如A<CL,A<C,A<B;以B結點為根結點的二叉樹也是二叉排序樹,在B結點的左子樹中的每一個結點的值都小于結點B的值,比如C<B,CL<B,CR<B),

具體操作如下圖:

如上圖,

要調整以A結點為根結點的二叉樹即"最小不平衡子樹"使其平衡,

調整的結果需要滿足:

  1. 恢復"最小不平衡子樹"的平衡

  2. 使得"最小不平衡子樹"在調整之后依然滿足二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值"

在本例中結點的大小關系為AL<A<CL<C<CR<B<BR,

使得以A結點為根結點的二叉樹即"最小不平衡子樹"恢復平衡的處理方法如下:

步驟一:讓C結點右旋->具體的做法就是讓C結點向右上旋轉代替B結點,C結點的右子樹就是以B結點為根結點的樹;

步驟二:處理子樹AL、CL、CR、BR->

  • 首先看子樹AL,AL之前是A結點的左子樹,AL的值小于A結點值(AL<A),所以只能把AL連接在A結點的左子樹,因為要保證"左子樹結點值<根結點值<右子樹結點值"

  • 再看子樹CL,CL之前是C結點的左子樹,有CL的值小于C結點的值(CL<C),所以CL繼續作為C結點的左子樹

  • 再看子樹CR,CR之前是C結點的右子樹,現在C結點的右子樹已經掛了B結點,那么CR就不能作為C結點的右子樹了,但是有CR的值小于B結點的值(CR<B),所以可以把子樹CR當作B結點的左子樹

  • 最后看子樹BR,BR之前是B結點的右子樹,有BR的值大于B結點的值(B<BR),所以BR繼續作為B結點的右子樹

此時得到了上述圖片中最中間的二叉樹->其中A結點的平衡因子=H-(H+2)=-2即A結點是不平衡的;B結點的平衡因子=(H-1)-H=-1即B結點是平衡的;C結點的平衡因子=H-(H+1)=-1即C結點是平衡的,只有A結點不平衡,所以繼續調整使得以A結點為根結點的二叉樹保持平衡,

步驟三:(上述圖片中最中間的二叉樹)讓C結點左旋->具體的做法就是讓C結點向左上旋轉代替A結點,C結點的左子樹就是以A結點為根結點的樹;

步驟四:處理子樹AL、CL、CR、BR->

  • 首先看子樹AL,AL之前是A結點的左子樹,AL的值小于A結點值(BL<B),所以只能把AL連接在A結點的左子樹,因為要保證"左子樹結點值<根結點值<右子樹結點值"

  • 再看子樹CL,CL之前是C結點的左子樹,現在C結點的左子樹已經掛了A結點,那么CL就不能作為C結點的左子樹了,但是有CL的值大于A結點的值(CL>A),所以可以把子樹CL當作A結點的右子樹

  • 再看子樹CR,CR之前是B結點的左子樹,有CR的值小于B結點的值(CR<B),所以CR繼續作為B結點的左子樹

  • 最后看子樹BR,BR之前是B結點的右子樹,有BR的值大于B結點的值(B<BR),所以BR繼續作為B結點的右子樹

這樣就可以既保證二叉排序樹的特性,同時BL這個部分的高度是H+1即成功插入了新結點,

經過上述的調整之后(上述圖片最右邊的樹)B結點的左子樹CR的高度為H-1、右子樹BR的高度為H,即B結點的平衡因子=(H-1)-H=-1,

A結點的左子樹AL的高度為H、右子樹CL的高度為H,即A結點的平衡因子=H-H=0,

C結點的左子樹的高度為H+1、右子樹的高度為H+1,即C結點的平衡因子=(H+1)-(H+1)=0,

可知以A結點為根結點的子樹、以B結點為根結點的子樹和以C結點為根結點的子樹都保持了平衡,

這樣一來就可以讓"最小不平衡子樹"恢復平衡,同時又保持二叉排序樹的特性。

注意:

如上圖,

本例假定插入的新結點在子樹CL上,

實際上也有可能是插入在子樹CR上,這種情況的處理方式同子樹CL,

也可以保證使所有的結點都恢復平衡。


五.LL、RR、LR和RL的總結:

  • 只有左孩子才能"右旋";只有右孩子才能"左旋"->每一次旋轉都會導致這個孩子變成爹,爹變成孩子


六.填坑:

以上述圖片中最左邊的二叉排序樹為例,

此時已經插入了關鍵字為67的結點,導致關鍵字為70的結點不平衡(平衡因子為2),導致該結點不平衡的原因是在其左孩子的左子樹上插入了一個新結點67,也就是"LL"型,

這種情況應該讓不平衡結點即關鍵字為70的結點的左孩子進行"右旋",也就是關鍵字為68的結點替代關鍵字為70的結點的位置,然后關鍵字為70的結點成為關鍵字為68的結點的右孩子,67結點連在68結點的左邊,

之前說過68的右子樹要成為70的左子樹,但原本68的右子樹是一個空樹NULL,把68的右子樹連接在70結點的左子樹后相當于結點70的左子樹為NULL,因此經過"右旋"操作之后得到的結果如上述圖片最右邊的二叉樹,

現在要填的坑是,剛開始說過只要把"最小不平衡子樹"恢復平衡之后其他所有的結點都會恢復平衡,現在來解釋一下為什么會這樣,

如下圖:

如上圖,

之前介紹了"LL"、"RR"、"LR"、"RL"四種情況,

對于這四類情況抽象的假設,

剛開始整棵二叉樹的高度為H+2,

插入新結點之后會導致不平衡,這棵"最小不平衡子樹"的高度為H+3,

但是經過旋轉一系列的處理之后二叉樹的整體高度又恢復了H+2,

如下圖:

如上圖:

所以這就能解釋為什么只需要調整"最小不平衡子樹"就能恢復整個二叉樹的平衡,

"最小不平衡子樹"變的不平衡是因為插入新結點后它的高度加1,但是經過調整之后"最小不平衡子樹"的高度又會恢復成原來的高度,

所以對于"最小不平衡子樹"的根結點的父結點來說,只要把該"最小不平衡子樹"的高度恢復原狀,

"最小不平衡子樹"的根結點的父結點的平衡因子也就會恢復原狀,同樣的再往上的祖先結點也都會跟著恢復原狀,

因此只要把"最小不平衡子樹"的高度恢復原狀,那么其他結點的平衡因子也都會依次恢復,

所以在這種插入操作中只需要調整"最小不平衡子樹","最小不平衡子樹"恢復平衡后,其他結點就都可以恢復平衡。


七.練習:

1.例一:

以上述圖片最左邊的二叉排序樹為例,

現在要插入關鍵字為90的結點,根據二叉排序樹的特性可知應該連接到關鍵字為70的結點的右子樹上,最終得到上述圖片中最右邊的二叉樹,

插入關鍵字為90的結點后,它的父結點即關鍵字為70的結點以及其祖先結點的平衡因子都可能受到影響,

所以可以從下到上依次檢查關鍵字為90的結點的父結點和祖先節點的平衡因子,

當檢查到關鍵字為66的結點后,發現是第一個不平衡的結點,平衡因子為-2,

因此以66結點為根結點的子樹就是"最小不平衡子樹",接下來只需要調整該"最小不平衡子樹"使其平衡即可,

66結點不平衡的原因是在它的右孩子68結點的右子樹中插入了一個新結點90,也就是"RR"型,

如下圖:

如上圖:

處理方式應該讓上述圖片中最右邊的二叉樹的不平衡結點66的右孩子68結點"左旋",替代66結點的位置,

如下圖:

如上圖,

上述圖片中最左邊的二叉樹的不平衡結點66的右孩子68結點"左旋","左旋"操作會導致68結點的左孩子67結點變成66結點的右孩子(詳情見本篇"RR"),最終得到上述圖片中最右邊的二叉樹,

最后一定要驗證得出的二叉樹是否滿足二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值",如果不滿足說明處理有問題,

經過調整之后,這棵"最小不平衡子樹"就恢復了平衡,同時其他的結點的平衡因子也恢復了平衡。

2.例二:

以上述圖片最左邊的二叉排序樹為例,

現在要插入關鍵字為63的結點,根據二叉排序樹的特性可知應該連接到關鍵字為60的結點的右子樹上,最終得到上述圖片中最右邊的二叉樹,

插入關鍵字為63的結點后,它的父結點即關鍵字為60的結點以及其祖先結點的平衡因子都可能受到影響,

所以可以從下到上依次檢查關鍵字為63的結點的父結點和祖先節點的平衡因子,

當檢查到關鍵字為50的結點后,發現是第一個不平衡的結點,平衡因子為-2,

因此以50結點為根結點的子樹就是"最小不平衡子樹",接下來只需要調整該"最小不平衡子樹"使其平衡即可,

50結點不平衡的原因是在它的右孩子68結點的左子樹中插入了一個新結點63,也就是"RL"型,

這種類型要做的處理就是把不平衡結點即50結點的右孩子68結點的左孩子66結點先"右旋",再"左旋",

如下圖:

如上圖:

處理方式是首先讓上述圖片中最左邊的二叉樹的結點66右旋替代結點68的位置,結點68成為結點66的右孩子,

結點66的右孩子67結點變為結點68的左子樹(詳情見本篇"RL"),

最終得到上述圖片中最右邊的二叉樹,

如下圖:

如上圖,

需要繼續"左旋"操作,讓上述圖片中最左邊的二叉樹的結點66進行"左旋"替代結點50的位置,左旋之后結點66的左子樹(以結點60為根結點的子樹)應該成為結點50的右子樹,結點50成為結點66的左孩子,最終得到上述圖片中最右邊的二叉樹,

這樣的話整棵樹恢復了平衡,同時依然保持了二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值"。

最后一定要驗證得出的二叉樹是否滿足二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值",如果不滿足說明處理有問題,

經過調整之后,這棵"最小不平衡子樹"就恢復了平衡,同時其他的結點的平衡因子也恢復了平衡。

3.例三:

以上述圖片最左邊的二叉排序樹為例,

現在要插入關鍵字為57的結點,根據二叉排序樹的特性可知應該連接到關鍵字為55的結點的右子樹上,最終得到上述圖片中最右邊的二叉樹,

插入關鍵字為57的結點后,它的父結點即關鍵字為55的結點以及其祖先結點的平衡因子都可能受到影響,

所以可以從下到上依次檢查關鍵字為57的結點的父結點和祖先節點的平衡因子,

當檢查到關鍵字為66的結點后,發現是第一個不平衡的結點,平衡因子為2,

因此以66結點為根結點的子樹就是"最小不平衡子樹",接下來只需要調整該"最小不平衡子樹"使其平衡即可,

66結點不平衡的原因是在它的左孩子50結點的右子樹中插入了一個新結點57,也就是"LR"型,

這種類型要做的處理就是把不平衡結點即66結點的左孩子50結點的右孩子60結點先"左旋",再"右旋",

如下圖:

如上圖:

將上述圖片中最左邊的二叉樹中的60結點先"左旋",再"右旋",最終得到上述圖片中最右邊的二叉樹(詳情見本篇"LR"),

這樣的話整棵樹恢復了平衡,同時依然保持了二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值"。

最后一定要驗證得出的二叉樹是否滿足二叉排序樹的特性即"左子樹結點值<根結點值<右子樹結點值",如果不滿足說明處理有問題,

經過調整之后,這棵"最小不平衡子樹"就恢復了平衡,同時其他的結點的平衡因子也恢復了平衡。


八.查找效率分析:

如上圖,

在一棵二叉排序樹中進行查找操作,查找效率主要來自于該二叉排序樹的高度(詳情見"7.5.二叉排序樹(英文縮寫為BST,又名二叉查找樹)"),

假設當前二叉排序樹的高度為h,那么查找任何一個關鍵字最多需要對比h次(詳情見"7.5.二叉排序樹(英文縮寫為BST,又名二叉查找樹)"),

所以在二叉排序樹中進行查找操作的時間復雜度不會超過O(h),也就意味著平均查找長度即ASL不會超過O(h),

由此可知分析平衡二叉樹的查找效率,其實就是分析該平衡二叉樹的高度到底有多高,

基于平衡二叉樹的特性,

用N(h)表示深度為h的平衡二叉樹含有的最少的結點個數,

當h為0時該平衡二叉樹為空樹,那么該平衡二叉樹的結點個數N0為0,

當h為1時該平衡二叉樹只有1個根結點,那么該平衡二叉樹的結點個數N1為1,

當h為2時該平衡二叉樹中,它的結點最少有2個即根結點和其左孩子或者右孩子,那么該平衡二叉樹的結點個數N2為2,

再基于平衡二叉樹"樹上任一結點的左子樹和右子樹的高度只差不超過1"的遞歸特性可以得出N(h)=N(h-1)+N(h-2)+1,

即高度為h的平衡二叉樹的結點個數最少的情況應該是1個根結點,加其左子樹,該左子樹的高度為h-1,同時要保證左子樹的結點數最小,再加其右子樹,該右子樹的高度為h-2,并且也要保證右子樹的結點數最小,

所以可知N3為4,N4為7,N5為12,以此類推,

因此如果一棵平衡二叉樹的結點總數N為9,那么它的高度h最大為4->它的高度不可能為3,因為現在有9個結點,已經超出了N4;它的高度要到5的話,最少需要12個結點,

所以對于總共有9個結點的平衡二叉樹來說,在這棵二叉樹上查找一個關鍵字,最壞的情況也就需要對比4次關鍵字。

如果平衡二叉樹的結點總數為N,高度為h,基于N(h)=N(h-1)+N(h-2)+1這個公式可以證明平衡二叉樹的最大高度是O(log?N)的數量級(推導過程可以參考"5.4.二叉樹的性質"),

而平衡二叉樹的最大高度又反應了在最壞情況下查找操作的時間復雜度,因此最壞情況下平衡二叉樹的ASL或者查找操作的時間復雜度為O(log?N)->推導過程很復雜,如下圖:


九.總結:


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88745.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88745.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88745.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenCV CUDA模塊設備層-----將指向共享內存(shared memory)的指針封裝成一個 tuple函數smem_tuple()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 OpenCV的cv::cudev模塊中的一個用于 CUDA 編程的輔助函數&#xff0c;用于將指向共享內存&#xff08;shared memory&#xff09;的指針封裝成一…

paddlepaddle在RTX40系安裝注意事項

1 安裝簡介 1.1 安裝注意事項 顯卡型號&#xff1a;RTX4090 驅動版本&#xff1a;550.54.14 宿主機cuda版本&#xff1a;12.4 安裝方式&#xff1a;conda 注意cuda和cudnn的搭配 最初安裝是為了使用PaddleOCR&#xff0c;根據官網提示需要安裝cuda和cudnn。這里最關鍵的就是針…

車載以太網-組播

目錄 車載以太網中的組播:從原理到車載應用**一、組播的核心概念與車載網絡價值****二、車載以太網組播的關鍵協議與機制**1. **組播IP地址管理(IGMP協議)**2. **組播數據鏈路層實現(MAC地址映射)****三、車載以太網組播的典型應用場景**1. **自動駕駛與傳感器數據分發**2…

【雅思播客013】what do you do

【dialog】 A: Oh, look, there’s Veronica and her boyfriend.She’s always going on about him at the of?ce. Oh, great, they saw us. They’re coming this way. B: Oh, man... C: Jessica! Arthur! Hi! I’d like you to meet my boyfriend Greg, he’s the VP. of q…

Freebsd 14.2系統下 wifi網卡硬件驅動軟件配置調試大全

Freebsd 14.2系統下&#xff0c;網卡是AX200 先檢查網卡sysctl net.wlan.devices sysctl net.wlan.devices 能識別出已經安裝的 sysctl net.wlan.devices net.wlan.devices: iwlwifi0配置wlan0 # ifconfig wlan0 create wlandev iwlwifi0 # ifconfig wlan0 up # ifconfig …

Python打卡:Day39

知識點回顧 圖像數據的格式&#xff1a;灰度和彩色數據模型的定義顯存占用的4種地方 模型參數梯度參數優化器參數數據批量所占顯存神經元輸出中間狀態 batchisize和訓練的關系 浙大疏錦行

使用 GcExcel .NET 將 Excel 導出為 PDF

引言 在企業級應用開發中&#xff0c;經常需要將Excel數據導出為PDF格式以便于共享和打印。GrapeCity Documents for Excel&#xff08;簡稱GcExcel&#xff09;作為一款高性能的.NET Excel組件&#xff0c;提供了強大的PDF導出功能。本文將詳細介紹如何使用GcExcel .NET實現E…

每日算法刷題Day39 6.26:leetcode前綴和2道題,用時1h20min

8. 2055.蠟燭之間的盤子(中等,學習替換查詢區間) 2055. 蠟燭之間的盤子 - 力扣&#xff08;LeetCode&#xff09; 思想 1.給你一個長桌子&#xff0c;桌子上盤子和蠟燭排成一列。給你一個下標從 0 開始的字符串 s &#xff0c;它只包含字符 * 和 | &#xff0c;其中 * 表示一…

jrebel 下載,安裝,激活步驟

參考地址&#xff1a; [筆記] 最新版 - JRebel 插件激活與配置教程 : 高效開發的必備指南_jrebel激活-CSDN博客https://blog.csdn.net/LuChangQiu/article/details/145547828 1、下載 2、激活地址&#xff1a; http://42.193.18.168:8088 ### 撿個便宜 - 交朋友吧 ###https://…

uniapp使用plus調取藍牙/usb打印

安卓使用usb調取打印機 /*** 安卓usb調取打印機*param { string | bytes[] } html 傳入的打印內容*傳入一段文本或一個bytes數組* returns*/ export const printUsb (html) > {return new Promise((resolve, reject) > {if (!window.plus) return reject(new Error(&qu…

區塊鏈數據結構:區塊與鏈式結構編碼

目錄 區塊鏈數據結構:區塊與鏈式結構編碼引言:區塊鏈的骨架1. 區塊鏈數據結構解析1.1 區塊結構組成1.2 區塊鏈可視化結構2. 區塊核心組件詳解2.1 區塊頭字段說明2.2 Merkle樹結構2.3 工作量證明機制3. Python實現區塊鏈數據結構3.1 區塊類實現3.2 區塊鏈類實現3.3 區塊鏈演示…

阿里推出 R1-Omni:將強化學習與可驗證獎勵(RLVR)應用于全模態大語言模型

從視頻中識別情感涉及許多細微的挑戰。僅依賴視覺或音頻信號的模型&#xff0c;往往無法準確捕捉這兩種模態之間的復雜相互作用&#xff0c;從而導致對情感內容的誤解。一個關鍵難題在于可靠地結合視覺線索&#xff08;如面部表情或肢體語言&#xff09;與聽覺信號&#xff08;…

【江科大】STM32F103C8T6 + TB6612 + N20編碼器減速電機《03-增量式PID定速控制》(增量式PID,定時器輸入捕獲,定時器編碼器)

STM32F103C8T6單片機+N20減速電機帶霍爾編碼器版PID閉環控制實驗演示 STM32F103C8T6 實現的電機轉速控制系統,基于 PWM 輸出驅動、編碼器采樣反饋、以及增量式 PID 算法進行控制。 /*** @file Encoder.c* @brief 增量式編碼器驅動程序* @details 使用TIM3定時器的編碼器…

【論文閱讀35】-PINN review(2021)

這篇綜述全面回顧了物理信息機器學習 的原理、應用、軟件實現、理論進展與未來發展趨勢&#xff0c;這樣即使數據稀疏、帶噪&#xff0c;也能保證預測結果符合物理規律&#xff0c;適合解決偏微分方程正問題、反問題、非線性動力學和多物理耦合系統等科學計算場景。 作者信息&…

深度學習初探:聚焦 Transformer 與 LLM 的核心世界

文章目錄 前言一、神經網絡基礎&#xff1a;智能的基石二、Transformer 架構&#xff1a;AI 新紀元的基石Transformer 的核心特性Transformer 的關鍵組件 三、 大語言模型概覽總結 前言 人工智能的浪潮正以前所未有的力量重塑世界&#xff0c;而這場變革的核心引擎之一&#x…

【開發雜談】Auto Caption:使用 Electron 和 Python 開發實時字幕顯示軟件

項目已開源到 GitHub&#xff0c;項目地址&#xff1a;HiMeditator/auto-captionhttps://github.com/HiMeditator/auto-caption 軟件下載(Windows平臺)&#xff1a;Releases HiMeditator/auto-captionhttps://github.com/HiMeditator/auto-caption/releases 你是否遇到過看外…

臨床項目范圍管理:確保項目聚焦與成功交付

一、核心目標 1.1 清晰定義項目邊界 1.1.1 明確項目目標 明確項目具體目標、可交付成果、研究活動、納入/排除標準、數據收集范圍等,為項目規劃、執行、監控和控制奠定基礎。 1.1.2 防止范圍蔓延 嚴格控制未經批準的變更,避免項目目標、活動或可交付成果超出最初約定,導致…

opi是什么

是的&#xff0c;當然可以&#xff01;您提出了一個非常好的問題。 opi 遠不止是一個 NVIDIA 驅動安裝器&#xff0c;它是一個非常強大的、專為 openSUSE 設計的**“超級安裝助手”**或“智能搜索工具”。 它的主要目的就是為了解決一個常見問題&#xff1a;“我想安裝一個軟…

【Go語言-Day 9】指針基礎:深入理解內存地址與值傳遞

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

如何使用 vue vxe-table 來實現一個產品對比表表格

如何使用 vue vxe-table 來實現一個產品對比表表格 查看官網&#xff1a;https://vxetable.cn 效果 代碼 <template><div class"demo-page-wrapper"><vxe-grid v-bind"gridOptions"><template #img11><vxe-image src"h…