データ構造とアルゴリズム--AVL木とJavaの実現を学びます

バランスの取れたバイナリツリー

平衡二分木も、それは、バイナリ検索ツリーのルールを継承し、AVL木と呼ばれています。
1とそれぞれ左サブツリーのノードと右の部分木の高さの差の最大差。
バイナリツリーのように、時間の複雑さがある削除(怠け者削除)、見つける、極端なケースとして平衡二分探索木として生成されませんO(LOGN)。挿入動作のツリーを調整する必要性は、時間の複雑さはわずかであるO(LOGN)。
以下に示すように:最初の画像ショーAVLツリー、第2のマップはAVL木ではありません

マップ
ここに画像を挿入説明

回転AVL木

各左の部分木のノードの差と右サブツリー間の最大高低差:インサートは、AVLツリー特性を満足する必要があります。ノードが再バランシングはAと呼ばれている必要があります。任意のノードはそれほど高度に不平衡最大2人の息子、二サブツリーの2点の差の高さを有しているからです。四のアンバランスな状況が発生します。

1.挿入された後、左側の息子の左部分木。

一度挿入の左息子の右部分木2.。

3.息子の左と右のサブツリーが挿入されたら。

4.挿入されたら、右の息子の右部分木。

両方の場合のために1,4平衡状態は、単一の回転によって達成することができます。場合について図2及び図3は、二重回転平衡条件によって達成することができます。
ステップ右回転:左回転[類似しました]

  1. 新しいノードを構築し、値は現在のノードの値に等しく、
  2. 現在のノードの右部分木として、新しいノードの右部分木
  3. 現在のノードの左部分木のような新しいノードの左サブツリー右部分木
  4. ノードの現在の値は、ノードの左サブツリーの値を変更します
  5. 現在のノードはサブツリーの左サブツリーを左左サブツリーに設定されています
  6. 現在のノードは、ノードの新しい右サブツリーとして設定されている
    例示の回転中:
    ここに画像を挿入説明
    ここに画像を挿入説明

実現AVL木

達成するためのコアコード:

/**
	 * 获取左子树的高度
	 * @return
	 */
	public int leftHeight() {
	if(left==null) {
			return 0;
		}
	return left.height();
	}
	/**
	 * 获取右子树的高度
	 * @param node
	 */
	public int rightHeight() {
		if(right==null) {
				return 0;
			}
		return right.height();
		}
		/*
 * 向子树中添加节点
 */
	public void add(Node node) {
		// TODO Auto-generated method stub
		if(node==null) {
			return;
		}
			//判断传入的节点的值比当前子树的根节点的值是大是小
			//添加的节点比当前结点更小
			if(node.value<this.value) {
				//如果左节点为空
				if(this.left==null) {
					this.left=node;
					//如果不为空
				}else {
					this.left.add(node);
				}
				//右子树
			}else {
				if(this.right==null) {
					this.right=node;
					//如果不为空
				}else {
					this.right.add(node);
				}
			}
			//查找是否平衡
			 //检查左子树和右子树的高度
			//进行右旋转
			if(leftHeight()-rightHeight()>=2) {
				//双旋转
				if(left!=null&&left.leftHeight()<left.rightHeight()) {
					//先左旋转
					left.leftRotate();
					//再右旋转
					RightRotate();
					//单旋转
				}else {
				RightRotate();
				}
			//左旋转	
			}
			if(leftHeight()-rightHeight()<=-2) {
				//双旋转
				if(right!=null&&right.rightHeight()<right.leftHeight()) {
					right.leftRotate();
					leftRotate();
					//单
				}else {
					leftRotate();
				}	
			}
		}
/**
 * 左旋转
 */
	private void leftRotate() {
		Node newLeft=new Node(value);
		newLeft.left=left;
		newLeft.right=right.left;
		value=right.value;
		right=right.right;
		left=newLeft;
}
	/**
	 * 右旋转
	 * @param node
	 */
	private void RightRotate() {
		//创建一个新节点,值等于当前节点的值
		Node newRight=new Node(value);
		//把新节点的右子树设置为当前结点的右子树
		newRight.right=right;
		//把新节点的左子树设置为当前结点的左子树的右子树
		newRight.left=left.right;
		//把当前结点的值换为左子树节点的值
		value=left.value;
		//把当前结点的左子树设置为左子树的 左子树
		left=left.left;
		//把当前结点的右子树设置为新节点
		right=newRight;	
}

達成するための完全なJavaコード:

package demo10;

public class Node {
	int value;
	Node left;
	Node right;
	
	public Node (int value) {
		this.value=value;
	}
	/**
	 * 返回当前结点的高度
	 * @param node
	 */
	public int height() {
		return Math.max(left==null?0:left.height(),right==null?0: right.height())+1;
	}
	/**
	 * 获取左子树的高度
	 * @return
	 */
	public int leftHeight() {
	if(left==null) {
			return 0;
		}
	return left.height();
	}
	/**
	 * 获取右子树的高度
	 * @param node
	 */
	public int rightHeight() {
		if(right==null) {
				return 0;
			}
		return right.height();
		}
	
/*
 * 向子树中添加节点
 */
	public void add(Node node) {
		// TODO Auto-generated method stub
		if(node==null) {
			return;
		}
			//判断传入的节点的值比当前子树的根节点的值是大是小
			//添加的节点比当前结点更小
			if(node.value<this.value) {
				//如果左节点为空
				if(this.left==null) {
					this.left=node;
					//如果不为空
				}else {
					this.left.add(node);
				}
				//右子树
			}else {
				if(this.right==null) {
					this.right=node;
					//如果不为空
				}else {
					this.right.add(node);
				}
			}
			//查找是否平衡
			 //检查左子树和右子树的高度
			//进行右旋转
			if(leftHeight()-rightHeight()>=2) {
				//双旋转
				if(left!=null&&left.leftHeight()<left.rightHeight()) {
					//先左旋转
					left.leftRotate();
					//再右旋转
					RightRotate();
					//单旋转
				}else {
				RightRotate();
				}
			//左旋转	
			}
			if(leftHeight()-rightHeight()<=-2) {
				//双旋转
				if(right!=null&&right.rightHeight()<right.leftHeight()) {
					right.leftRotate();
					leftRotate();
					//单
				}else {
					leftRotate();
				}	
			}
		}
/**
 * 左旋转
 */
	private void leftRotate() {
		Node newLeft=new Node(value);
		newLeft.left=left;
		newLeft.right=right.left;
		value=right.value;
		right=right.right;
		left=newLeft;
}
	/**
	 * 右旋转
	 * @param node
	 */
	private void RightRotate() {
		//创建一个新节点,值等于当前节点的值
		Node newRight=new Node(value);
		//把新节点的右子树设置为当前结点的右子树
		newRight.right=right;
		//把新节点的左子树设置为当前结点的左子树的右子树
		newRight.left=left.right;
		//把当前结点的值换为左子树节点的值
		value=left.value;
		//把当前结点的左子树设置为左子树的 左子树
		left=left.left;
		//把当前结点的右子树设置为新节点
		right=newRight;	
}

	
	
/*
 * 中序遍历二叉排序,中序遍历二叉排序树结果为从小到大的顺序
 */
	public void midShow(Node node) {
		if(node==null) {
			return;
		}
		midShow(node.left);
		System.out.println(node.value);
		midShow(node.right);
	}
	/**
	 * 查找节点
	 */
	public Node search(int value) {
		if(this.value==value){
			return this;
	}else if(value<this.value){
		if(left==null) {
			return null;
		}
		return left.search(value);
	}else{
		if(right==null) {
			return null;
		}
		return right.search(value);
		}
	}
	/**
	 * 搜索父节点
	 */
	public Node searchParent(int value) {
		if((this.left!=null&&this.left.value==value)||(this.right!=null&&this.right.value==value)) {
			return this;
		}else {
			if(this.value>value&&this.left!=null) {
				return this.left.searchParent(value);
			}else if(this.value<value&&this.right!=null){
				return this.right.searchParent(value);
			}
			return null;
		}
	}
}
package demo10;

public class BinarySortTree {
	Node root;
	/*
	 * 向二叉排序树中添加节点
	 */
	public void add(Node node) {
		//如果是一颗空树
		if(root==null) {
			root=node;
		}else {
			root.add(node);
		}
	}
	/*
	 * 中序遍历二叉排序树
	 */
	public void midShow() {
		if(root!=null) {
			root.midShow(root);
		}
	}
	/*
	 * 查找节点
	 */
	public Node search(int value) {
		if(root==null) {
			return null;
		}else {
			return root.search(value);
		}
	}
	
	/**
	 * 删除节点
	 */
	public void delete(int value) {
		if(root==null) {
			return;
		}else {
			//找到这个节点
			Node target=search(value);
			//如果没有这个节点
			if(target==null) {
				return;
			}
			//找到他的父节点
			 Node parent=searchParent(value);
			//要删除的节点是叶子节点
			 if(target.left==null&&target.right==null) {
				 //要删除的节点是父节点的左子节点
				 if(parent.left.value==value) {
					 parent.left=null;
					 //要删除的节点是右节点
				 }else {
					 parent.right=null;
				 }
				 //要删除的节点有两个子节点 
			 }else if(target.left!=null&&target.right!=null) {
				 //删除右子树中值最小的节点,取刚获取到该节点的值
				 int min=deleteMin(target.right);
				 //替换目标节点中的值
				 target.value=min;
				//要删除的节点有一个左子节点或右字节点 
			 }else {
				 if(target.left!=null) {
					 //
					 if(parent.left.value==value) {
						 parent.left=target.left;
						 //要删除的节点是右节点
					 }else {
						 parent.right=target.right;
					 }
					 
				//右子节点	 
				 }else {
					 if(parent.right.value==value) {
						 parent.right=target.right;
						 //要删除的节点是右节点
					 }else {
						 parent.right=target.right;
					 }
					 
				 }
			 }
		}
	}
	/**
	 * 删除一颗树中最小的值的节点
	 * @param right
	 * @return
	 */
	private int deleteMin(Node node) {
		Node target=node;
		//递归向左找
		while(target.left!=null) {
			target=target.left;
		}
		//删除最小值的这个节点
		delete(target.value);
		return target.value;
	}
	/*
	 * 搜索父节点
	 */
	public Node searchParent(int value) {
		if(root==null) {
			return null;
		}else {
			return root.searchParent(value);
		}
	}
}
package demo10;

public class TestBinarySortTree {
	public  static void main(String[] args) {
	//int [] arr=new int [] {8,9,6,7,5,4};
	int [] arr=new int [] {8,9,5,4,6,7};
	//创建一颗二叉排序树
	BinarySortTree bst=new  BinarySortTree();
	//循环添加
	for(int i:arr) {
		bst.add(new Node(i));
		}
	System.out.println(bst.root.height());
	System.out.println(bst.root.value);
	}
}

学び、要約するには、次の記事へこの記事コンテンツを参照。
バランスの取れたバイナリツリー

公開された28元の記事 ウォンの賞賛5 ビュー3718

おすすめ

転載: blog.csdn.net/qq_42711899/article/details/104607373