作者
NeroJings
來源
https://blog.csdn.net/zhang6622056/article/details/82698859
正文部分見:平衡二叉樹 AVL樹結構詳解 [Java實現]
完整源碼
package focus.zhishui.tree; import java.util.ArrayList; import java.util.List; /** * * Created by Nero on 2018-09-11. */ public class AvlTreeInteger { /*** * 遍歷方式, * 1-前序遍歷 * 2-中序遍歷 * 3-後序遍歷 * 4-層級遍歷 */ public static final int QIANXU = 1; public static final int ZHONGXU = 2; public static final int HOUXU = 3; public static final int CENGJI = 4; private AvlNodeInteger root; private int size; public AvlTreeInteger() { } public AvlTreeInteger(AvlNodeInteger root) { this.root = root; } private void initRoot(Integer val){ AvlNodeInteger AvlNodeInteger = new AvlNodeInteger(val); this.root = AvlNodeInteger; System.out.println(this.root.getValue()); } /**** * 對外開放,插入操作 * @param val * @throws Exception */ public void insert(Integer val) throws Exception { if(null == root){ initRoot(val); size++; return; } if(contains(val)) throw new Exception("The value is already exist!"); insertNode(this.root,val); size++; } private AvlNodeInteger createSingleNode(Integer val){ return new AvlNodeInteger(val); } /** * 遞歸插入 * parent == null 到最底部插入前節點判斷情況 * @param parent * @param val * @return */ private AvlNodeInteger insertNode(AvlNodeInteger parent,Integer val){ if(parent == null){ return createSingleNode(val); } if(val < parent.getValue()){ //插入判斷,小於父節點,插入到右邊 //注意理解回溯,這裏最終返回的是插入完成節點 //每一層回溯,都會返回相應當時遞歸的節點!!! parent.setLeft(insertNode(parent.getLeft(),val)); //判斷平衡,不要在意這裏的parent是誰, //這個parent肯定是遞歸層級上,回溯的一個節點!每一個節點都需要判斷平衡 if(height(parent.getLeft()) - height(parent.getRight()) > 1){ Integer compareVal = (Integer) parent.getLeft().getValue(); //左左旋轉類型 if(val < Integer.valueOf(compareVal)){ parent = leftLeftRotate(parent); }else{ //左右旋轉類型 parent = leftRightRotate(parent); } } } if(val > parent.getValue()){ //插入判斷,小於父節點,插入到右邊 //注意理解回溯,這裏最終返回的是插入完成節點 //每一層回溯,都會返回相應當時遞歸的節點!!! parent.setRight(insertNode(parent.getRight(),val)); //判斷平衡,不要在意這裏的parent是誰, //這個parent肯定是遞歸層級上,回溯的一個節點!每一個節點都需要判斷平衡 if(height(parent.getRight()) - height(parent.getLeft()) > 2){ Integer compareVal = (Integer) parent.getLeft().getValue(); if(val > compareVal){ parent = rightRightRotate(parent); }else{ parent = rightLeftRotate(parent); } } } parent.setHeight((maxHeight(parent.getLeft(),parent.getRight()))+1); return parent; } /*** * 左左旋轉模型 * @param node 旋轉之前的parent node 節點 * @return 旋轉之後的parent node節點 */ private AvlNodeInteger leftLeftRotate(AvlNodeInteger node){ AvlNodeInteger newRoot = node.getLeft(); node.setLeft(newRoot.getRight()); newRoot.setRight(node); //由此node的高度降低了,newRoot的高度提高了。 //newRoot的高度由node的高度而來 node.setHeight(maxHeight(node.getLeft(),node.getRight())+1); newRoot.setHeight(maxHeight(newRoot.getLeft(),newRoot.getRight())+1); return newRoot; } /*** * 右右旋轉模型 * @param node * @return */ private AvlNodeInteger rightRightRotate(AvlNodeInteger node){ AvlNodeInteger newRoot = node.getRight(); node.setRight(newRoot.getLeft()); newRoot.setLeft(node); //由此node的高度降低了,newRoot的高度提高了。 //newRoot的高度由node的高度而來 node.setHeight(maxHeight(node.getLeft(),node.getRight())); newRoot.setHeight(maxHeight(newRoot.getLeft(),newRoot.getRight())); return newRoot; } /** * 左右模型,先右右,再左左 * @param node * @return */ private AvlNodeInteger leftRightRotate(AvlNodeInteger node){ //注意傳遞的參數 node.setLeft(rightRightRotate(node.getLeft())); return leftLeftRotate(node); } /*** * 右左模型,先左左,在右右 * @param node * @return */ private AvlNodeInteger rightLeftRotate(AvlNodeInteger node){ node.setRight(leftLeftRotate(node.getRight())); return rightRightRotate(node); } /*** * 求左右子節點最大高度 * @param left * @param right * @return */ private int maxHeight(AvlNodeInteger left,AvlNodeInteger right){ return height(left) > height(right) ? height(left) : height(right); } /*** * 求一個節點的高度 * @param t * @return */ private int height(AvlNodeInteger t){ return null == t ? 0 : t.getHeight(); } public boolean contains(Integer val) { AvlNodeInteger curNode = root; if(null == curNode) return false; while(null != curNode){ if(val > curNode.getValue()){ curNode = curNode.getRight(); }else if(val < curNode.getValue()){ curNode = curNode.getLeft(); }else{ return true; } } return false; } public void remove(Integer val) { if(null == val || null == root){ return; } if(!contains(val)){ return; } remove(root,val); } /**** * AVL刪除,平衡樹實現 * @param parent * @param val * @return */ private AvlNodeInteger remove(AvlNodeInteger parent,Integer val){ if(val < parent.getValue()){ //左子樹遞歸查詢 //刪除以後返回替換的新節點 AvlNodeInteger newLeft = remove(parent.getLeft(),val); parent.setLeft(newLeft); //檢查是否平衡,刪除的左邊,那麼用右邊-左邊 if(height(parent.getRight()) - height(parent.getLeft()) > 1){ AvlNodeInteger tempNode = parent.getRight(); if(height(tempNode.getLeft()) > height(tempNode.getRight())){ //RL類型 rightLeftRotate(parent); }else{ //RR類型 rightRightRotate(parent); } } }else if(val > parent.getValue()){ //右子樹遞歸查找 //刪除以後返回替換的新節點 AvlNodeInteger newRight = remove(parent.getRight(),val); parent.setRight(newRight); //檢查是否平衡 if(height(parent.getLeft()) - height(parent.getRight()) > 1){ AvlNodeInteger tempNode = parent.getLeft(); if(height(tempNode.getLeft()) > height(tempNode.getRight())){ //LL類型 leftLeftRotate(parent); }else{ //LR類型 leftRightRotate(parent); } } }else{ //相等,匹配成功 if(null != parent.getLeft() && null != parent.getRight()){ //左右子節點都不爲空 //判斷高度,高的一方,拿到最大(左),最小(右)的節點,作爲替換節點。 //刪除原來匹配節點 //左邊更高,獲取到左邊最大的節點 if(parent.getLeft().getHeight() > parent.getRight().getHeight()){ AvlNodeInteger leftMax = getMax(parent.getLeft()); parent.setLeft(remove(parent.getLeft(),leftMax.getValue())); leftMax.setLeft(parent.getLeft()); leftMax.setRight(parent.getRight()); leftMax.setHeight(maxHeight(leftMax.getLeft(),leftMax.getRight())); parent = leftMax; }else{ //右邊更高,獲取到右邊最小的節點 AvlNodeInteger rightMin = getMin(parent.getRight()); parent.setRight(remove(parent.getRight(),rightMin.getValue())); rightMin.setLeft(parent.getLeft()); rightMin.setRight(parent.getRight()); rightMin.setHeight(maxHeight(parent.getLeft(),parent.getRight())+1); parent = rightMin; } }else{ //有任意一方節點爲空,則不爲空的那一方作爲替換節點,刪除原來的節點 parent = null; } } return parent; } /*** * 刪除時用到,獲取當前節點子節點最大值 * @param currentRoot * @return */ private AvlNodeInteger getMax(AvlNodeInteger currentRoot){ if(currentRoot.getRight() != null){ currentRoot = getMax(currentRoot.getRight()); } return currentRoot; } /*** * 刪除時用到,獲取當前節點子節點最小值 * @param currentRoot * @return */ private AvlNodeInteger getMin(AvlNodeInteger currentRoot){ if(currentRoot.getLeft() != null){ currentRoot = getMin(currentRoot.getLeft()); } return currentRoot; } public AvlNodeInteger findMax() { if(null == root) return null; AvlNodeInteger temp = root; while(null != temp.getRight()){ temp = temp.getRight(); } return temp; } public AvlNodeInteger findMin() { if(null == root) return null; AvlNodeInteger temp = root; while(null != temp.getLeft()){ temp = temp.getLeft(); } return temp; } public int getNodeSize() { return size; } public void printGraph(int style) { if(root == null){ return; } if(style == 1){ xianxu(root); }else if(style == 2){ zhongxu(root); }else if(style == 3){ houxu(root); }else if(style == 4){ List a = new ArrayList<>(); a.add(root); cengji(a); } } /*** * 前序編譯 * 1-根節點 * 2-左節點 * 3-右節點 * 根左右 * @param parent */ private void xianxu(AvlNodeInteger parent){ System.out.println(parent.getValue()); if(null != parent.getLeft()){ xianxu(parent.getLeft()); } if(null != parent.getRight()){ xianxu(parent.getRight()); } } /*** * 中序遍歷 * 左節點 * 根節點 * 右節點 * * * 左根右 * @param parent */ private void zhongxu(AvlNodeInteger parent){ if(null != parent.getLeft()){ zhongxu(parent.getLeft()); } System.out.println(parent.getValue()); if(null != parent.getRight()){ zhongxu(parent.getRight()); } } /*** * 後續遍歷 * 左右根 * 左節點 * 右節點 * 根節點 */ private void houxu(AvlNodeInteger parent){ if(null != parent.getLeft()){ houxu(parent.getLeft()); } if(null != parent.getRight()){ houxu(parent.getRight()); } System.out.println(parent); } /*** * 層級遍歷 * @param parent */ private void cengji(List<AvlNodeInteger> parent){ if(null == parent || parent.size() == 0) return; //打印當前層 List<AvlNodeInteger> AvlNodeIntegers = new ArrayList<AvlNodeInteger>(); int k = 0; for(int i = 0 ; i < parent.size() ; i++){ AvlNodeInteger currentNode = parent.get(i); System.out.println(currentNode.getValue()+","); if(null != currentNode.getLeft()){ AvlNodeIntegers.add(currentNode.getLeft()); k++; } if(null != currentNode.getRight()){ AvlNodeIntegers.add(currentNode.getRight()); k++; } } System.out.println("--------------------------"); cengji(AvlNodeIntegers); } public static class AvlNodeInteger{ private Integer value; private Integer height; private AvlNodeInteger left; private AvlNodeInteger right; public AvlNodeInteger(int t){ initNode(t,null,null,1); } public AvlNodeInteger(int t,AvlNodeInteger left,AvlNodeInteger right){ initNode(t,left,right,null); } private void initNode(int t,AvlNodeInteger left,AvlNodeInteger right,Integer height){ this.setValue(t); this.left = left; this.right = right; this.height = height; } public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } public Integer getHeight() { return height; } public void setHeight(Integer height) { this.height = height; } public AvlNodeInteger getLeft() { return left; } public void setLeft(AvlNodeInteger left) { this.left = left; } public AvlNodeInteger getRight() { return right; } public void setRight(AvlNodeInteger right) { this.right = right; } } }