private void balance(Node node){ Node parent = node.getParent(); Node node_middle = node; Node node_prev = node; Boolean avl = true; do{ if(node_middle == parent.getLeft() && (-1 <= parent.getAVL()-1 && parent.getAVL()-1 <= 1)){ //node_middle爲parent的左樹,此時parent左樹高度+1不會形成不平衡。 parent.subAVL(); node_prev = node_middle; node_middle = parent; //因爲上面對parent的平衡值進行了修改,若是修改後的平衡值爲0,說明此時parent節點的高度沒有改變,以前較短的左樹高度+1,變爲與右樹高度相同。 if(parent != null && parent.getAVL() == 0) parent = null; else parent = parent.getParent(); }else if(node_middle == parent.getRight() && (-1 <= parent.getAVL()+1 && parent.getAVL()+1 <= 1)){ //node_middle爲parent的右樹,此時parent右樹高度+1不會形成不平衡。 parent.addAVL(); node_prev = node_middle; node_middle = parent; //因爲上面對parent的平衡值進行了修改,若是修改後的平衡值爲0,說明此時parent節點的高度沒有改變,以前較短的右樹高度+1,變爲與左樹高度相同。 if(parent != null && parent.getAVL() == 0) parent = null; else parent = parent.getParent(); }else{//出現最小不平衡節點,新增時不須要考慮更高節點,因此直接中斷循環,調用平衡方法 avl = false; } }while(parent != null && avl); if(parent == null){ return; } //選擇相應的旋轉方式 chooseCalculation(parent, node_middle, node_prev); }
3.二、刪除node
public void deleteNode(int item){ Node node = get(item); if(node == null) return; Node parent = node.getParent(); if(!node.hasChild()){//葉子節點 if(parent == null){//刪除最後節點 root = null; return; } if(node.hasBrother()){//node有兄弟節點時,須要判斷是否須要調用平衡方法 if(node == parent.getLeft()) isBalance(node, 1); else isBalance(node, -1); parent.deleteChildNode(node); }else{//node沒有兄弟節點時,高度減一,須要進行平衡 deleteAvl(node); parent.deleteChildNode(node); } }else if(node.getLeft() != null && node.getRight() == null){//有一個子節點時,將子節點上移一位,而後進行平衡便可 if(parent == null){//刪除的是根節點 root = node; return; } if(node == parent.getLeft()){ parent.setLeft(node.getLeft()); }else{ parent.setRight(node.getLeft()); } node.getLeft().setParent(parent); deleteAvl(node.getLeft()); }else if(node.getLeft() == null && node.getRight() != null){//有一個子節點時,將子節點上移一位,而後進行平衡便可 if(parent == null){//刪除的是根節點 root = node; return; } if(node == parent.getRight()){ parent.setRight(node.getRight()); }else{ parent.setLeft(node.getRight()); } node.getRight().setParent(parent); deleteAvl(node.getRight()); } else{//有兩個子節點時,先在節點左樹尋找最大節點last,而後刪除last,最後將被刪除節點的value替換爲last的value Node last = findLastNode(node); int tmp = last.getValue(); deleteNode(last.getValue()); node.setValue(tmp); } node = null;//GC }
private void LeftLeftRotate(Node node){ Node parent = node.getParent(); if(parent.getParent() != null && parent == parent.getParent().getLeft()){ node.setParent(parent.getParent()); parent.getParent().setLeft(node); }else if(parent.getParent() != null && parent == parent.getParent().getRight()){ node.setParent(parent.getParent()); parent.getParent().setRight(node); }else{ root = node; node.setParent(null); } parent.setParent(node); parent.setLeft(node.getRight()); if(node.getRight() != null) node.getRight().setParent(parent); node.setRight(parent); if(node.getAVL() == -1){//只有左節點時,parent轉換後沒有子節點 parent.setAVL(0); node.setAVL(0); }else if(node.getAVL() == 0){//node有兩個子節點,轉換後parent有一個左節點 parent.setAVL(-1); node.setAVL(1); }//node.getAVL()爲1時會調用左右旋轉 }
private void RightRightRotate(Node node){ Node parent = node.getParent(); if(parent.getParent() != null && parent == parent.getParent().getLeft()){ node.setParent(parent.getParent()); parent.getParent().setLeft(node); }else if(parent.getParent() != null && parent == parent.getParent().getRight()){ node.setParent(parent.getParent()); parent.getParent().setRight(node); }else{ root = node; node.setParent(null); } parent.setParent(node); parent.setRight(node.getLeft()); if(node.getLeft() != null) node.getLeft().setParent(parent); node.setLeft(parent); if(node.getAVL() == 1){ node.setAVL(0); parent.setAVL(0); }else if(node.getAVL() == 0){//當node有兩個節點時,轉換後層數不會更改,左樹比右樹高1層,parent的右樹比左樹高一層 parent.setAVL(1); node.setAVL(-1); } }
private void LeftRightRotate(Node node){ Node parent = node.getParent(); Node child = node.getRight(); //左右旋轉時node的avl必爲1,因此只需考慮child的avl if(!child.hasChild()){ node.setAVL(0); parent.setAVL(0); }else if(child.getAVL() == -1){ node.setAVL(0); parent.setAVL(1); }else if(child.getAVL() == 1){ node.setAVL(-1); parent.setAVL(0); }else if(child.getAVL() == 0){ node.setAVL(0); parent.setAVL(0); } child.setAVL(0); //第一次交換 parent.setLeft(child); node.setParent(child); node.setRight(child.getLeft()); if(child.getLeft() != null) child.getLeft().setParent(node); child.setLeft(node); child.setParent(parent); //第二次交換 if(parent.getParent() != null && parent == parent.getParent().getLeft()){ child.setParent(parent.getParent()); parent.getParent().setLeft(child); }else if(parent.getParent() != null && parent == parent.getParent().getRight()){ child.setParent(parent.getParent()); parent.getParent().setRight(child); }else{ root = child; child.setParent(null); } parent.setParent(child); parent.setLeft(child.getRight()); if(child.getRight() != null) child.getRight().setParent(parent); child.setRight(parent); }
3.3.四、右左旋轉git
private void RightLeftRotate(Node node){ Node parent = node.getParent(); Node child = node.getLeft(); if(!child.hasChild()){ node.setAVL(0); parent.setAVL(0); }else if(child.getAVL() == -1){ node.setAVL(1); parent.setAVL(0); }else if(child.getAVL() == 1){ node.setAVL(0); parent.setAVL(-1); }else if(child.getAVL() == 0){ parent.setAVL(0); node.setAVL(0); } child.setAVL(0); //第一次交換 parent.setRight(child); node.setParent(child); node.setLeft(child.getRight()); if(child.getRight() != null) child.getRight().setParent(node); child.setRight(node); child.setParent(parent); //第二次交換 if(parent.getParent() != null && parent == parent.getParent().getLeft()){ child.setParent(parent.getParent()); parent.getParent().setLeft(child); }else if(parent.getParent() != null && parent == parent.getParent().getRight()){ child.setParent(parent.getParent()); parent.getParent().setRight(child); }else{ root = child; child.setParent(null); } parent.setParent(child); parent.setRight(child.getLeft()); if(child.getLeft() != null) child.getLeft().setParent(parent); child.setLeft(parent); }
完整代碼github地址:https://github.com/ziyuanjg/AVLTreegithub