AVL树双旋转+图解
生活随笔
收集整理的這篇文章主要介紹了
AVL树双旋转+图解
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
圖解
代碼實(shí)現(xiàn)
package com.atguigu.avl; /*** @創(chuàng)建人 wdl* @創(chuàng)建時(shí)間 2021/3/30* @描述*/ public class AVLTreeDemo {public static void main(String[] args) { // int[] arr={4,3,6,5,7,8};//創(chuàng)建一個(gè)AVLTree對象 // int arr[]={10,12,8,9,7,6};int[] arr={10,11,7,6,8,9};AVLTree avlTree = new AVLTree();//添加for (int i = 0; i < arr.length; i++) {avlTree.add(new Node(arr[i]));}//遍歷System.out.println("中序遍歷");avlTree.infixOrder();System.out.println("在平衡處理后");System.out.println(avlTree.getRoot().height());System.out.println(avlTree.getRoot().leftHeight());System.out.println(avlTree.getRoot().rightHeight());System.out.println("當(dāng)前的根節(jié)點(diǎn)"+avlTree.getRoot());} }//創(chuàng)建AVLTree class AVLTree{private Node root;public Node getRoot() {return root;}//查找要 刪除的節(jié)點(diǎn)public Node search(int value){if (root==null){return null;}else {return root.search(value);}}//查找父節(jié)點(diǎn)public Node searchParent(int value){if (root==null){return null;}else {return root.searchParent(value);}}//編寫方法//1.返回的是以node為根節(jié)點(diǎn)的二叉排序樹的最小節(jié)點(diǎn)的值//2.刪除以node為根節(jié)點(diǎn)的二叉排序樹的最小節(jié)點(diǎn)/**** @param node 傳入的節(jié)點(diǎn)(當(dāng)做一顆二叉排序樹的根節(jié)點(diǎn))* @return 返回的是以node為根節(jié)點(diǎn)的二叉排序樹的最小節(jié)點(diǎn)的值*/public int delRightTreeMin(Node node){Node target=node;//循環(huán)的查找左節(jié)點(diǎn),就會找到最小值while (target.left!=null){target=target.left;}//這時(shí)target就指向了最小節(jié)點(diǎn)//刪除最小節(jié)點(diǎn)delNode(target.value);return target.value;}//刪除節(jié)點(diǎn)public void delNode(int value){if(root==null){return;}else {//1.需求先找到要?jiǎng)h除節(jié)點(diǎn)targetNodeNode targetNode = search(value);//如果沒有找到要?jiǎng)h除的節(jié)點(diǎn)if(targetNode==null){return;}//如果我們發(fā)現(xiàn)targetNode沒有父節(jié)點(diǎn)//如果們發(fā)現(xiàn)當(dāng)前這顆二叉排序樹只有一個(gè)節(jié)點(diǎn)if (root.left==null&&root.right==null){root=null;return;}//去找到targetNode的父節(jié)點(diǎn)Node parent = searchParent(value);//如果要?jiǎng)h除的節(jié)點(diǎn)是葉子節(jié)點(diǎn)if(targetNode.left==null&&targetNode.right==null){//判斷targetNode是父節(jié)點(diǎn)的左子節(jié)點(diǎn),還是右子節(jié)點(diǎn)if (parent.left!=null&&parent.left.value==value){//是左子節(jié)點(diǎn)parent.left=null;}else if (parent.right!=null&&parent.right.value==value){//是右子節(jié)點(diǎn)parent.right=null;}}else if(targetNode.left!=null&&targetNode.right!=null){//刪除有兩顆子樹的節(jié)點(diǎn)int minVal=delRightTreeMin(targetNode.right);targetNode.value=minVal;}else {//刪除只有一顆子樹的節(jié)點(diǎn)//如果要要?jiǎng)h除的節(jié)點(diǎn)有左子節(jié)點(diǎn)if (targetNode.left!=null){if(parent!=null){if (parent.left.value==value){//是左子節(jié)點(diǎn)parent.left=targetNode.left;}else{//是右子節(jié)點(diǎn)parent.right=targetNode.left;}}else {root=targetNode.left;}}else{ //如果要要?jiǎng)h除的節(jié)點(diǎn)有右子節(jié)點(diǎn)if (parent!=null){if (parent.left.value==value){//是左子節(jié)點(diǎn)parent.left=targetNode.right;}else{//是右子節(jié)點(diǎn)parent.right=targetNode.right;}}else {root=targetNode.right;}}}}}//添加節(jié)點(diǎn)的方法public void add(Node node){if(root==null){root=node;//如果root為空直接讓root指向node}else {root.add(node);}}//中序遍歷public void infixOrder(){if(root!=null){root.infixOrder();}else {System.out.println("二叉排序樹為空,不能遍歷");}}}//創(chuàng)建Node節(jié)點(diǎn) class Node{int value;Node left;Node right;public Node(int value) {this.value = value;}//返回左子樹的高度public int leftHeight(){if(left==null){return 0;}return left.height();}//返回右子樹的高度public int rightHeight(){if(right==null){return 0;}return right.height();}//返回當(dāng)前節(jié)點(diǎn)的高度,以該節(jié)點(diǎn)為根節(jié)點(diǎn)的樹的高度public int height(){return Math.max(left==null?0:left.height(),right==null?0:right.height())+1;}//左旋轉(zhuǎn)方法private void leftRotate(){//創(chuàng)建新的節(jié)點(diǎn),以當(dāng)前根節(jié)點(diǎn)的值Node newNode = new Node(value);//把新的節(jié)點(diǎn)的左子樹設(shè)置成當(dāng)前節(jié)點(diǎn)的左子樹newNode.left=left;//把新的節(jié)點(diǎn)的右子樹設(shè)置成當(dāng)前節(jié)點(diǎn)的右子樹的左子樹newNode.right=right.left;//把當(dāng)前節(jié)點(diǎn)的值替換成右子節(jié)點(diǎn)的值value=right.value;//把當(dāng)前節(jié)點(diǎn)的右子樹設(shè)置成右子樹的右子樹right=right.right;//把當(dāng)前節(jié)點(diǎn)的左子樹(左子節(jié)點(diǎn))設(shè)置成新的節(jié)點(diǎn)left=newNode;}//右旋轉(zhuǎn)private void rightRotate(){Node newNode = new Node(value);newNode.right=right;newNode.left=left.right;value=left.value;left=left.left;right=newNode;}//查找要?jiǎng)h除的節(jié)點(diǎn)/**** @param value 希望刪除的節(jié)點(diǎn)的值* @return 如果找到返回該節(jié)點(diǎn),否則返回null*/public Node search(int value){if(value==this.value){//找到就是該節(jié)點(diǎn)return this;}else if (value<this.value){//如果查找的值小于當(dāng)前節(jié)點(diǎn),向左子樹遞歸查找//如果左子節(jié)點(diǎn)為空if(this.left==null){return null;}return this.left.search(value);}else {//如果查找的值不小于當(dāng)前節(jié)點(diǎn),向右子樹遞歸查找//如果右子節(jié)點(diǎn)為空if(this.right==null){return null;}return this.right.search(value);}}//查找要?jiǎng)h除節(jié)點(diǎn)的父節(jié)點(diǎn)/**** @param value 要找到的節(jié)點(diǎn)的值* @return 返回的是要?jiǎng)h除節(jié)點(diǎn)的父節(jié)點(diǎn),如果沒有就返回null*/public Node searchParent(int value){//如果當(dāng)前節(jié)點(diǎn)就是要?jiǎng)h除的節(jié)點(diǎn)的父節(jié)點(diǎn),就返回if((this.left!=null&&this.left.value==value)||(this.right!=null&&this.right.value==value)){return this;}else {//如果查找的值小于當(dāng)前節(jié)點(diǎn)的值,并且當(dāng)前節(jié)點(diǎn)的左子節(jié)點(diǎn)不為空if(value<this.value&&this.left!=null){return this.left.searchParent(value);//向左子樹遞歸查找}else if(value>=this.value&&this.right!=null){return this.right.searchParent(value);//向右子樹遞歸查找}else {return null;//沒有找到父節(jié)點(diǎn)}}}@Overridepublic String toString() {return "Node{" +"value=" + value +'}';}//添加節(jié)點(diǎn)的方法//遞歸的形式添加節(jié)點(diǎn),注意需要二叉排序樹的要求public void add(Node node){if(node==null){return;}//判斷傳入節(jié)點(diǎn)的值,和當(dāng)前子樹的根節(jié)點(diǎn)的值得關(guān)系if(node.value<this.value){//如果當(dāng)前節(jié)點(diǎn)的左子節(jié)點(diǎn)為nullif(this.left==null){this.left=node;}else {//遞歸的向左子樹添加this.left.add(node);}}else {//添加的節(jié)點(diǎn)的值大于當(dāng)前節(jié)點(diǎn)的值//如果當(dāng)前節(jié)點(diǎn)的左子節(jié)點(diǎn)為nullif(this.right==null){this.right=node;}else {//遞歸的向右子樹添加this.right.add(node);}}//當(dāng)添加完一個(gè)節(jié)點(diǎn)后,如果(右子樹的高度-左子樹的高度)>1,左旋轉(zhuǎn)if (rightHeight()-leftHeight()>1){//如果它的右子樹的左子樹的高度大于它的右子樹的告訴if(right!=null&&right.leftHeight()>right.rightHeight()){//先對當(dāng)前節(jié)點(diǎn)的右節(jié)點(diǎn)(右子樹)->右旋轉(zhuǎn)right.rightRotate();//再對當(dāng)前節(jié)點(diǎn)進(jìn)行左旋轉(zhuǎn)leftRotate();}else {//直接進(jìn)行左旋轉(zhuǎn)即可leftRotate();}return;//必須要!!!}//當(dāng)添加完一個(gè)節(jié)點(diǎn)后,如果(左子樹的高度-右子樹的高度)>1,右旋轉(zhuǎn)if (leftHeight()-rightHeight()>1){//如果它的左子樹的右子樹的高度大于它的左子樹的告訴if(left!=null&&left.rightHeight()>left.leftHeight()){//先對當(dāng)前節(jié)點(diǎn)的左節(jié)點(diǎn)(左子樹)->左旋轉(zhuǎn)left.leftRotate();//再對當(dāng)前節(jié)點(diǎn)進(jìn)行右旋轉(zhuǎn)rightRotate();}else {//直接進(jìn)行右旋轉(zhuǎn)即可rightRotate();}}}//中序遍歷public void infixOrder(){if(this.left!=null){this.left.infixOrder();}System.out.println(this);if (this.right!=null){this.right.infixOrder();}}}總結(jié)
以上是生活随笔為你收集整理的AVL树双旋转+图解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 石林在哪里 石林的简介
- 下一篇: 图的快速入门