数据结构与算法
AVL Tree
关于平衡二叉树的定义,功能已在上期讲过啦,当我重新思考AVLTree时发现我上期的代码可以优化,更加精巧,具一般性,话不多说,代码如下:
package TwelveWeek;
/**
* in class and I think it's perfect both in inset and remove!
* @author Hello
*
*/
public class AVLNode2 {
private class Node{
public Node left;
public Node right;
public int key;
public int height;
public Node(){}
public Node(int x){this.key=x;}
public Node(int x, int y){this.key=x; this.height=y;}
}
public Node root;
private static int allow_balance=1;
public AVLNode2(){}
public boolean isEmpty(){return this.root==null;}
public void insert(int x) throws Exception{root=insert(root, x);}
private Node insert(Node node, int x)throws Exception{
if(node==null) return new Node(x);
if(x > node.key){
node.right=insert(node.right, x);
if(height(node.right)-height(node.left) > allow_balance){
if(height(node.right.right) >=height( node.right.left)) node=rotate_with_right(node);
else node=double_with_right(node);
}
}
else if(x < node.key){
node.left=insert(node.left, x);
if(height(node.left)-height(node.right) > allow_balance){
if(height(node.left.left) >= height(node.left.right)) node=rotate_with_left(node);
else node=double_with_left(node);
}
}
else throw new Exception("The number you input is already exist.");
node.height=1+Math.max(height(node.left), height(node.right));
return node;
}
private int height(Node node){return (node==null) ? 0 : 1+Math.max(height(node.left), height(node.right));}
private Node rotate_with_right(Node node) {
// TODO Auto-generated method stub
if(node==null) return null;
Node repnode=node.right;
node.right=repnode.left;
repnode.left=node;
return repnode;
}
private Node rotate_with_left(Node node) {
// TODO Auto-generated method stub
if(node==null) return null;
Node repnode=node.left;
node.left=repnode.right;
repnode.right=node;
return repnode;
}
private Node double_with_right(Node node) {
// TODO Auto-generated method stub
if(node==null) return null;
node.right=rotate_with_left(node.right);
return rotate_with_right(node);
}
private Node double_with_left(Node node) {
// TODO Auto-generated method stub
if(node==null) return null;
node.left=rotate_with_right(node.left);
return rotate_with_left(node);
}
public void remove(int x)throws Exception{root=remove(root, x);}
private Node remove(Node node, int x)throws Exception{
if(node==null) throw new Exception("The number you want to remove is't exist.");
if(x > node.key){
node.right=remove(node.right, x);
if(height(node.right)-height(node.left) > allow_balance){
if(height(node.right.right) >=height( node.right.left)) node=rotate_with_right(node);
else node=double_with_right(node);
}
if(height(node.left)-height(node.right) > allow_balance){
if(height(node.left.left) >= height(node.left.right)) node=rotate_with_left(node);
else node=double_with_left(node);
}
}
else if(x < node.key){
node.left=remove(node.left, x);
if(height(node.right)-height(node.left) > allow_balance){
if(height(node.right.right) >=height( node.right.left)) node=rotate_with_right(node);
else node=double_with_right(node);
}
if(height(node.left)-height(node.right) > allow_balance){
if(height(node.left.left) >= height(node.left.right)) node=rotate_with_left(node);
else node=double_with_left(node);
}
}
else{
if(node.left!=null&&node.right!=null){
Node repnode=getmin(node.right);
repnode.right=remove(node.right, repnode.key);
repnode.left=node.left;
node=repnode;
}
else node=(node.left==null) ? node.right : node.left;
}
return node;
}
private Node getmin(Node node) {
// TODO Auto-generated method stub
if(node==null) return null;
while(node.left!=null) node=node.left;
return new Node(node.key);
}
public void preTravel() throws Exception{ preTravel(root);}
private void preTravel(Node node) throws Exception{
if(node==null) return;
Stack s=new Stack(20);
s.push(node);
while(!s.isEmpty()){
node=(Node) s.pop();
visit(node);
if(node.right!=null) s.push(node.right);
if(node.left!=null) s.push(node.left);
}
System.out.println();
}
public void midTravel() throws Exception{ midTravel(root);}
private void midTravel(Node node) throws Exception{
if(node==null) return;
Stack s=new Stack(20);
while(true){
while(node!=null){
s.push(node);
node=node.left;
}
if(s.isEmpty()) break;
node=(Node) s.pop();
visit(node);
node=node.right;
}
System.out.println();
}
public void bacTravel() throws Exception{ bacTravel(root);}
private void bacTravel(Node node) throws Exception {
if(node==null) return;
Stack s=new Stack(20);
Node curnode=node;
Node prenode=null;
while(curnode!=null){
s.push(curnode);
curnode=curnode.left;
}
while(!s.isEmpty()){
curnode=(Node) s.pop();
if(curnode.right==null||curnode.right==prenode){
visit(curnode);
prenode=curnode;
continue;
}
s.push(curnode);
curnode=curnode.right;
while(curnode!=null){
s.push(curnode);
curnode=curnode.left;
}
}
System.out.println();
}
private void visit(Node temp) {
// TODO Auto-generated method stub
System.out.print(temp.key+", ");
}
}
Test
package TwelveWeek;
import java.util.*;
public class AVLNodeTest {
public static void main(String args[]) throws Exception{
AVLNode as=new AVLNode();
as.insert(1);
as.insert(2);
as.insert(3);
as.insert(4);
as.insert(5);
as.insert(6);
as.insert(7);
as.insert(8);
as.insert(9);
System.out.println("pre in the first time: ");
as.preTravel();
System.out.println("mid");
as.midTravel();
System.out.println("bac");
as.bacTravel();
System.out.println();
AVLNode2 ad=new AVLNode2();
ad.insert(1);
ad.insert(2);
ad.insert(3);
ad.insert(4);
ad.insert(5);
ad.insert(6);
ad.insert(7);
ad.insert(8);
ad.insert(9);
System.out.println("pre in the second time: ----------");
ad.preTravel();
System.out.println("mid");
ad.midTravel();
System.out.println("bac");
ad.bacTravel();
ad.remove(5);
System.out.println("pre (removed): ----------");
ad.preTravel();
ad.insert(5);
System.out.println("pre (recovery): ----------");
ad.preTravel();
}
}
result:
pre in the first time:
4, 2, 1, 3, 6, 5, 8, 7, 9,
mid
1, 2, 3, 4, 5, 6, 7, 8, 9,
bac
1, 3, 2, 5, 7, 9, 8, 6, 4,
pre in the second time: ----------
4, 2, 1, 3, 6, 5, 8, 7, 9,
mid
1, 2, 3, 4, 5, 6, 7, 8, 9,
bac
1, 3, 2, 5, 7, 9, 8, 6, 4,
pre (removed): ----------
4, 2, 1, 3, 8, 6, 7, 9,
pre (recovery): ----------
4, 2, 1, 3, 8, 6, 5, 7, 9,