Learning data structures and algorithms --AVL tree and realization of java

Balanced binary tree

Balanced binary tree is also called AVL tree, it inherits the rules of binary search tree.
1 and a maximum difference in height difference of each left subtree node and the right subtree.
As the binary tree will not produce as balanced binary search tree as an extreme case, so find, delete (lazy deletion) the time complexity is o (logn). Need to adjust the inserting operation tree, the time complexity is slightly o (logn).
As shown below: first picture shows the AVL tree, the second map is not the AVL tree

Map
Here Insert Picture Description

Rotation AVL tree

Inserts need satisfying AVL tree characteristics: a maximum height difference between a difference of each left subtree node and the right subtree. The node must re-balancing is called a. Since any node has at most two sons, so when highly unbalanced, a height of two subtree 2 point difference. Four unbalanced situation will occur:

1. The left subtree of a left son once inserted.

2. On the right subtree of the left son of a once inserted.

3. The left and right sub-tree of a son once inserted.

4. a right subtree of the right son once inserted.

For both cases 1,4 equilibrium conditions can be achieved by a single rotation. For Cases 2 and 3 can be achieved by a double-rotation equilibrium conditions.
Step right rotation: left rotation [similar]

  1. Build a new node, the value equal to the value of the current node,
  2. The right subtree of the new node as the current node's right subtree
  3. Left subtree right subtree of the new node as the current node's left subtree
  4. The current value of the node to change the value of the left subtree of node
  5. The current node is set to the left subtree left subtree left subtree
  6. The current node is set as a new right subtree of the node
    during the rotation of illustration:
    Here Insert Picture Description
    Here Insert Picture Description

Realization AVL tree

The core code to achieve:

/**
	 * 获取左子树的高度
	 * @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;	
}

Complete java code to achieve:

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);
	}
}

This article content reference to the following article to learn and summary.
Balanced binary tree

Published 28 original articles · won praise 5 · Views 3718

Guess you like

Origin blog.csdn.net/qq_42711899/article/details/104607373