バランスの取れたバイナリツリー
平衡二分木も、それは、バイナリ検索ツリーのルールを継承し、AVL木と呼ばれています。
1とそれぞれ左サブツリーのノードと右の部分木の高さの差の最大差。
バイナリツリーのように、時間の複雑さがある削除(怠け者削除)、見つける、極端なケースとして平衡二分探索木として生成されませんO(LOGN)。挿入動作のツリーを調整する必要性は、時間の複雑さはわずかであるO(LOGN)。
以下に示すように:最初の画像ショーAVLツリー、第2のマップはAVL木ではありません
回転AVL木
各左の部分木のノードの差と右サブツリー間の最大高低差:インサートは、AVLツリー特性を満足する必要があります。ノードが再バランシングはAと呼ばれている必要があります。任意のノードはそれほど高度に不平衡最大2人の息子、二サブツリーの2点の差の高さを有しているからです。四のアンバランスな状況が発生します。
1.挿入された後、左側の息子の左部分木。
一度挿入の左息子の右部分木2.。
3.息子の左と右のサブツリーが挿入されたら。
4.挿入されたら、右の息子の右部分木。
両方の場合のために1,4平衡状態は、単一の回転によって達成することができます。場合について図2及び図3は、二重回転平衡条件によって達成することができます。
ステップ右回転:左回転[類似しました]
- 新しいノードを構築し、値は現在のノードの値に等しく、
- 現在のノードの右部分木として、新しいノードの右部分木
- 現在のノードの左部分木のような新しいノードの左サブツリー右部分木
- ノードの現在の値は、ノードの左サブツリーの値を変更します
- 現在のノードはサブツリーの左サブツリーを左左サブツリーに設定されています
- 現在のノードは、ノードの新しい右サブツリーとして設定されている
例示の回転中:
実現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);
}
}
学び、要約するには、次の記事へこの記事コンテンツを参照。
バランスの取れたバイナリツリー