1. 程式人生 > 其它 >GBU610-ASEMI智慧家居整流橋GBU610

GBU610-ASEMI智慧家居整流橋GBU610

一:AVL樹的概念

概念:
平衡二叉樹也叫二叉搜尋樹又被稱為AVL樹,可以保證查詢效率較高。它是一棵空樹或者它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。平衡二叉樹的實現方法有紅黑樹、AVL、替罪羊樹、Treap、伸展樹等。

二:AVL樹左旋轉思路

當右子樹的高度比左子樹高度大1時,進行左旋轉。
首先假定一棵二叉樹 [4,3,6,5,7,8]

第一步:建立一個新的節點,值為當前根節點的值 【4】
第二步:將新節點【4】的左子樹設定為當前節點【根節點】的左子樹
第三步:把新節點【4】的右子樹設定為當前節點【根節點】的右子樹的左子樹

第四步:將當前節點【根節點】的值變為右子節點【6】的值
第五步:把當前節點【根節點】的右子樹設定為右子樹的右子樹
第六步:將當前節點的左子樹設定為新節點

最終節點【6】被當作垃圾回收
在實現程式碼之前,我們需要知道的一個核心的操作:
我們需要知道左右子樹的高度是多少,因為只有當左右子樹的高度差大於1才需要進行旋轉。
計算高度程式碼實現:

//返回左子樹的高度
public int leftHeight(){
      if(left == null){
          return 0;
      }
    return left.height();
}
//返回右子樹的高度
public int rightHeight(){
      if(right == null){
          return 0;
      }
    return right.height();
}
//返回以當前節點為根節點的高度
public int height(){
      return Math.max(left == null ? 0: left.height(), right == null ? 0: right.height())+1;
 }

左旋轉方法程式碼

private void leftRotate(){

       //1.建立新的節點,值為根節點的值
       Node newnode = new Node(value);
       //2.將新節點的左子樹設定為當前節點的左子樹
       newnode.left = this.left;
       //3.將新節點的右子樹設定為當前節點右子樹的左子樹
       newnode.right = this.right.left;
       //4.將當前節點的值設定為右子節點的值
       this.value = this.right.value;
       //5.將當前節點的右子樹設定為右子樹的右子樹
       this.right = this.right.right;
       //6.將當前節點的左子樹設定為新節點
       this.left = newnode;
}

三:AVL樹右旋轉思路

當左子樹的高度比右子樹的高度大1時,需要進行右旋轉。
首先假定一棵二叉樹 [10,12,8,9,7,6]

第一步:建立一個新的節點,值為當前根節點的值【10】
第二步:將新節點【10】的右子樹設定為當前節點的右子樹【12】
第三步:將新節點【10】的左子樹設定為當前節點的左子樹的右子樹【9】

第四步:將當前節點【10】的值設定為左子節點【8】的值
第五步:將當前節點【8】的左子樹設定為左子樹的左子樹【7】
第六步:將當前節點【8】的右子樹設定為新節點【10】

最後:節點【8】被當作垃圾回收

同樣我們需要計算出左右子樹的高度,程式碼與左旋轉一樣。
右旋轉方法程式碼:

private void rightRotate(){

     //1.建立一個新的節點,值為當前根節點的值
         Node newNode = new Node(value);
     //2.將新節點的右子樹設定為當前節點的右子樹
         newNode.right = this.right;
     //3.將新節點的左子樹設定為當前節點的左子樹的右子樹
         newNode.left = this.left.right;
     //4.將當前節點的值設定為左子節點的值
         this.value = this.left.value;
     //5.將當前節點的左子樹設定為左子樹的左子樹
         this.left = this.left.left;
     //6.將當前節點的右子樹設定為新節點
         this.right = newNode;
}

在上述兩個數列中單旋轉就可以將非平衡二叉樹轉成平衡二叉樹,但是左/右旋轉在某些情況下不能將非平衡樹轉成平衡樹。比如:【10,11,7,6,8,9】那麼這個時候就需要採用雙旋轉了。

四:AVL樹雙旋轉思路

假定一棵二叉樹 [10,11,7,6,8,9]

問題分析:
1.當前節點【10】的左子樹的右子樹的高度大於它的左子樹的高度
解決方法:
1.首先對當前節點【10】的左子樹進行左旋轉
2.再對當前節點【10】進行右旋轉即可
程式碼實現:

//新增完一個節點以後,如果(左子樹的高度 - 右子樹的高度) > 1,右旋轉
if(leftHeight() - rightHeight() > 1){
    //判斷它的左子樹的右子樹高度是否比左子樹高
    if(left.rightHeight() > left.leftHeight()){
        //對當前結點的左子樹進行左旋轉
        left.leftRotate();
        //再進行右旋轉
        rightRotate();
    }else{
        //直接進行右旋轉
        rightRotate();
    }
    return;  //返回,防止進入下面的操作  
}

同理,另一種情況(右子樹的左子樹高度大於右子樹的高度)
解決思路:
1.首先對當前節點的右子樹進行右旋轉
2.再對當前節點進行左旋轉
程式碼實現:

//新增完一個節點以後,如果(右子樹的高度 - 左子樹的高度) > 1,左旋轉
if(rightHeight() - leftHeight() > 1){
    //判斷它的右子樹的左子樹高度是否比右子樹高
    if(right.leftHeight() > right.rightHeight()){
        //對當前結點的右子樹進行右旋轉
        right.rightRotate();
        //再進行左旋轉
        leftRotate();
    }else{
        //直接進行左旋轉
        leftRotate();
    }
    return;
}

完。