前提:默认树中不会有相同的值出现
实现了平衡二叉树基本的插入、删除、修改。考虑的情况可能不那么完整,欢迎给予建议~
整体代码如下:
import java.util.LinkedList;
class TreeNode{
int value;
TreeNode(int value){
this.value=value;
}
TreeNode left;
TreeNode right;
int height;
}
public class AVLTree {
//获得高度
public int getHeight(TreeNode t){
if(t==null) return 0;
return Math.max(getHeight(t.left), getHeight(t.right))+1;
}
//插入节点
public TreeNode insertNode(TreeNode root,int item){
System.out.println("Insert "+item+" now:");
//假设item是不和树中所有节点重复的值
if(root==null){
//树为空的时候
root=new TreeNode(item);
root.height=0;
}
else if(item<root.value){
//树不空,要插入的item小于root,递归插入左子树。
root.left=insertNode(root.left, item);
if((getHeight(root.left)-getHeight(root.right))>1){
if(item<root.left.value){
//插在了root的左儿子的左结点,root失去平衡
root=singlewithLeft(root);
}else{
//插在了root的左儿子的右节点,root失去平衡
root=doublewithLeft(root);
}
}
}else{
root.right=insertNode(root.right, item);
if((getHeight(root.right)-getHeight(root.left))>1){
if(item>root.right.value){
//插在了root右儿子的右节点,root失去平衡
root=singlewithRight(root);
}else {
//插在了root的右儿子的左结点,root失去平衡
root=doublewithRight(root);
}
}
}
return root;
}
//查询
public boolean queryNode(TreeNode root,int item){
//查询树中是否有节点的值是item,有返回true,否则返回False
if(item==root.value){
return true;
}else if(root.left!=null && item<root.value){
return queryNode(root.left, item);
}else if (root.right!=null && item>root.value) {
return queryNode(root.right, item);
}
return false;
}
//删除
public TreeNode deleteNode(TreeNode root,int item){
//删除值为item的节点
if(item==root.value){
if(root.left==null || root.right==null){
if(root.left!=null) root=root.left;
else if(root.right!=null) root=root.right;
else root=null;
}else{
TreeNode tr=root.right;
if(tr.left!=null){
while(tr.left!=null) tr=tr.left;
root.value=tr.value;
tr=null;
}else{
root.value=tr.value;
root.right=tr.right;
tr=null;
}
//调整本层的root
root=fixBalance(root);
}
}else if(item<root.value){
root.left=deleteNode(root.left, item);
//回溯的过程中调整上一层的root
root=fixBalance(root);
}else{
root.right=deleteNode(root.right, item);
//回溯的过程中调整上一层的root
root=fixBalance(root);
}
return root;
}
//修改
public TreeNode updateNode(TreeNode root,int olditem,int newitem){
//将值为olditem的节点的值更新为newitem,然后重新平衡
//采取的方法是删除值为olditem的节点,插入值为newitem的节点
root=deleteNode(root, olditem);
return insertNode(root, newitem);
}
//平衡,用于删除节点的时候
public TreeNode fixBalance(TreeNode t){
System.out.println("fixBalance :"+ t.value);
if((getHeight(t.left)-getHeight(t.right))>1){
//左子树比右子树高
TreeNode tl=t.left;
if(tl.left!=null && (tl.left.left!=null || tl.left.right!=null)){
//左儿子的左子树加了节点
System.out.println("fix by singlewithleft");
return singlewithLeft(t);
}
if(tl.right!=null && (tl.right.left!=null || tl.right.right!=null)){
//左儿子的右子树加了节点
System.out.println("fix by doublewithleft");
return doublewithLeft(t);
}
}
if((getHeight(t.right)-getHeight(t.left))>1){
//右子树比左子树高
TreeNode tr=t.right;
if(tr.left!=null && (tr.left.left!=null|| tr.left.right!=null)){
//右儿子的左子树加了节点
System.out.println("fix by doublewithright");
return doublewithRight(t);
}
if(tr.right!=null && (tr.right.left!=null || tr.right.right!=null)){
System.out.println("fix by singlewithright");
return singlewithRight(t);
}
}
return t;
}
//判断一棵树是不是平衡树
public boolean isAVL(TreeNode root){
if(root==null) return true;
if(root.left==null && root.right==null){
if(Math.abs(getHeight(root.left)-getHeight(root.right))>1){
return false;
}
}
return isAVL(root.left)&&isAVL(root.right);
}
//向右转
public TreeNode singlewithLeft(TreeNode t){
//左儿子的左结点插入了新的节点
System.out.println("A");
TreeNode tl=t.left;
TreeNode tlr=tl.right;
tl.right=t;
t.left=tlr;
t.height=getHeight(t);
tl.height=getHeight(tl);
return tl;
}
//向左转
public TreeNode singlewithRight(TreeNode t){
System.out.println("B");
//右儿子的右节点插入了新的节点
TreeNode tr=t.right;
TreeNode trl=tr.left;
t.right=trl;
tr.left=t;
t.height=getHeight(t);
tr.height=getHeight(tr);
return tr;
}
//先向左转,再右转
public TreeNode doublewithLeft(TreeNode t){
System.out.println("C");
//左儿子的右子树插入了新的节点
TreeNode tleft=t.left;
t.left=singlewithRight(tleft);
return singlewithLeft(t);
}
//先向右转,再左转
public TreeNode doublewithRight(TreeNode t){
System.out.println("D");
//右儿子的左子树插入了新的节点
t.right=singlewithLeft(t.right);
return singlewithRight(t);
}
//层次遍历
public void printByCeng(TreeNode root){
//层次遍历 空的地方填充-1
if(root==null) {
return;
}
LinkedList<TreeNode> q=new LinkedList<TreeNode>();
q.add(root);
while(q.size()!=0){
TreeNode pNode=q.poll();
if(pNode.value==-1){
System.out.println(pNode.value);
}else{
System.out.println(pNode.value);
if(pNode.left!=null){
q.add(pNode.left);
}else if(pNode.right!=null){
q.add(new TreeNode(-1));
}
if(pNode.right!=null){
q.add(pNode.right);
}else if(pNode.left!=null){
q.add(new TreeNode(-1));
}
}
}
}
public static void main(String args[]){
AVLTree test=new AVLTree();
int[] nums={2,9,7,11,5,23,48,34};
int i=0;
TreeNode root = null;
while(i<nums.length){
int item=nums[i++];
root=test.insertNode(root, item);
test.printByCeng(root);
}
System.out.println("----------------------");
test.printByCeng(root);
System.out.println("----------------------");
System.out.println("delete 5:");
root=test.deleteNode(root, 5);
test.printByCeng(root);
System.out.println("----------------------");
System.out.println("delete 23");
root=test.deleteNode(root, 23);
test.printByCeng(root);
System.out.println("----------------------");
System.out.println("update 34 to 1");
root=test.updateNode(root, 34, 1);
test.printByCeng(root);
System.out.println("----------------------");
System.out.println("query 7");
System.out.println(test.queryNode(root, 7));
System.out.println("query 66");
System.out.println(test.queryNode(root, 66));
}
}
/*
Output:
Insert 2 now:
2
Insert 9 now:
Insert 9 now:
2
-1
9
Insert 7 now:
Insert 7 now:
Insert 7 now:
D
A
B
7
2
9
Insert 11 now:
Insert 11 now:
Insert 11 now:
7
2
9
-1
11
Insert 5 now:
Insert 5 now:
Insert 5 now:
7
2
9
-1
5
-1
11
Insert 23 now:
Insert 23 now:
Insert 23 now:
Insert 23 now:
B
7
2
11
-1
5
9
23
Insert 48 now:
Insert 48 now:
Insert 48 now:
Insert 48 now:
7
2
11
-1
5
9
23
-1
48
Insert 34 now:
Insert 34 now:
Insert 34 now:
Insert 34 now:
Insert 34 now:
D
A
B
7
2
11
-1
5
9
34
23
48
----------------------
7
2
11
-1
5
9
34
23
48
----------------------
delete 5:
fixBalance :2
fixBalance :7
fix by singlewithright
B
11
7
34
2
9
23
48
----------------------
delete 23
fixBalance :34
fixBalance :11
11
7
34
2
9
-1
48
----------------------
update 34 to 1
fixBalance :11
Insert 1 now:
Insert 1 now:
Insert 1 now:
Insert 1 now:
A
7
2
11
1
-1
9
48
----------------------
query 7
true
query 66
false
*/