JAVA学习之路06——数据结构—>AVL树

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class AVLTree<K extends Comparable<K>,V> {
	private class Node{
		public K key;
		public V val;
		public Node left;
		public Node right;
		public int height;//节点高度
		public Node(K key,V val) {
			// TODO 自动生成的构造函数存根
			this.key=key;
			this.val=val;
			this.left=null;
			this.right=null;
			this.height=1;//默认新的节点高度值为1
		}
	}
	private int size;//节点个数
	private Node root;//根节点
	public AVLTree() {
		// TODO 自动生成的构造函数存根
		root=null;
		size=0;
	}
	public int getSize() {
		return size;
	}
	//计算节点的高度
	private int getHeight(Node cur) {
		if(cur==null)//空节点高度为0
			return 0;
		return cur.height;
	}
	//计算节点的平衡因子
	//左子树比右子树高为正,反之为负
	private int getBalanceFactor(Node cur) {
		if(cur==null)
			return 0;
		return getHeight(cur.left)-getHeight(cur.right);
	}
	public boolean isEmpty() {
		return size==0;
	}
	//添加节点
	public void add(K key,V val) {
		root=add(key,val,root);
	}
	//返回插入新节点后的二叉树的根
	private Node add(K key,V val,Node node) {
		if(node==null) {
			size++;
			return new Node(key,val);
		}
		if(key.compareTo(node.key)<0) {//小往左
			node.left=add(key,val,node.left);
		}else if(key.compareTo(node.key)>0) {//大往右
			node.right=add(key,val,node.right);
		}else
			node.val=val;//相等 更新Val值
		//平衡维护后返回
		return toBalance(node);
	}
	//返回维护好平衡的根节点
	private Node toBalance(Node cur) {
		//0、更新高度值
		cur.height=1+Math.max(getHeight(cur.left), getHeight(cur.right));
		//1、计算本节点的平衡因子
		int balanceFactor=getBalanceFactor(cur);
		//2、平衡维护
		//(1)新插入的节点在本节点左孩子的左侧
		if(balanceFactor>1&&getBalanceFactor(cur.left)>=0)
			return rightRotate(cur);
		//(2)新插入节点在本节点右孩子的右侧
		if(balanceFactor<-1&&getBalanceFactor(cur.right)<=0)
			return leftRotate(cur);
	//(3)新插入的节点在本节点左孩子的右侧
		//                 cur                          cur                          cLR                             
		//                /   \                        /   \    对cur右旋转         /   \  
		//       cur.left(cL)  a                    cLR     a       -->            cL    cur     
		//              /   \      对cL左旋转       / \                           /  \  /  \  
		//             c    cLR       -->          cL  b                         c   d  b   a
		//                 /   \                   /\                              
		//                d     b                 c  d                                                  
		if(balanceFactor>1&&getBalanceFactor(cur.left)<=0) {
			cur.left=leftRotate(cur.left);
			return rightRotate(cur);
		}
		//(4)新插入的节点在本节点右孩子的左侧
		if(balanceFactor<-1&&getBalanceFactor(cur.right)>=0) {
			cur.right=rightRotate(cur.right);
			return leftRotate(cur);
		}
		return cur;

	}
	//当插入节点在本节点左子树的左侧时,进行右旋转
	//                 cur                             cur.left(cL)                            
	//                /   \                               /     \
	//       cur.left(cL)  a                 -->        new      cur    
	//              /   \                                      /     \            
	//            new   cL.right(cLR)                  cL.right(cLR)  a 
	private Node rightRotate(Node cur) {
		Node cL=cur.left;;
		cur.left=cL.right;
		cL.right=cur;
		//更新高度
		cur.height=1+Math.max(getHeight(cur.left), getHeight(cur.right));
		cL.height=1+Math.max(getHeight(cL.left), getHeight(cL.right));
		return cL;
	}
	//当插入节点在本节点右子树的右侧时,进行左旋转
	//                 cur                             cur.right(cR)                            
	//                /   \                               /     \
	//               a  cur.right(cR)         -->       cur     new   
	//                    /   \                        /   \            
	//           cR.left(cRL)  new                    a    cR.left(cRL)
	private Node leftRotate(Node cur) {
		Node cR=cur.right;
		cur.right=cR.left;
		cR.left=cur;
		//更新高度
		cur.height=1+Math.max(getHeight(cur.left),getHeight(cur.right));
		cR.height=1+Math.max(getHeight(cR.left), getHeight(cR.right));
		return cR;
	}

	//判断是否为一棵二叉树
	public boolean isBST() {
		ArrayList<K> keys=new ArrayList<K>();
		//中序遍历整棵树,结果存在数组中,若满足二叉树性质,中序遍历之后数组中元素从小到大排列。
		inOrder(root,keys);
		//如果数组前一个元素大于后一个元素,说明不是一棵二叉树。
		for(int i=1;i<keys.size();i++)
			if(keys.get(i-1).compareTo(keys.get(i))>0)
				return false;
		return true;
	}
	//将这棵树中序遍历后放入数组
	private void inOrder(Node node,ArrayList<K>keys) {
		if(node==null)
			return;
		inOrder(node.left,keys);
		keys.add(node.key);
		inOrder(node.right,keys);
	}
	//判断当前的二叉树是否是平衡二叉树
	public boolean isBalance() {
		return isBalance(root);
	}
	//辅助函数
	private boolean isBalance(Node cur) {
		if(cur==null)
			return true;
		int balanceFactor=getBalanceFactor(cur);//获取平衡因子
		if(Math.abs(balanceFactor)>1)//如果平衡因子的绝对值大于1,则不平衡
			return false;
		return isBalance(cur.left)&&isBalance(cur.right);
	}


	//查询节点中是否包含某个元素
	public boolean contains(K key) {
		return contains(root,key);
	}
	private boolean contains(Node node ,K key) {
		if(node==null) 
			return false;
		if(node.key.compareTo(key)==0) 
			return true;
		else if(key.compareTo(node.key)>0) 
			return contains(node.right,key);
		else
			return contains(node.left,key);

	}
	//前序遍历
	public void preOrder() {
		preOrder(root);
	}
	private void preOrder(Node node) {
		if (node==null)
			return ;
		//先处理本节点,再处理左右(这里做打印处理
		System.out.println(node.key+","+node.val);
		preOrder(node.left);
		preOrder(node.right);
	}
	//前序遍历非递归实现
	public void preOrderNR() {
		Stack<Node> stack=new Stack<>();
		stack.push(root);
		while(!stack.isEmpty()) {
			Node cur=stack.pop();
			System.out.println(cur.key+","+cur.val);
			if(cur.right!=null)
				stack.push(cur.right);
			if(cur.left!=null)
				stack.push(cur.left);
		}
	}
	//中序遍历
	public void inOrder() {
		inOrder(root);
	}
	private void inOrder(Node node) {
		if(node==null)
			return;
		inOrder(node.left);
		System.out.println(node.key+","+node.val);
		inOrder(node.right);
	}
	//后续遍历
	public void postOrder() {
		postOrder(root);
	}
	private void postOrder(Node node) {
		if(node==null)
			return;
		postOrder(node.left);
		postOrder(node.right);
		System.out.println(node.key+","+node.val);
	}
	//层序遍历
	public void levelOrder() {
		Queue<Node> q=new LinkedList<>();
		q.add(root);
		while(!q.isEmpty()) {
			Node cur=q.remove();
			System.out.println(cur.key+","+cur.val);
			if(cur.left!=null)
				q.add(cur.left);
			if(cur.right!=null)
				q.add(cur.right);

		}
	}
	//查询最小值
	public K findMin() {
		Node node=root;
		while(node.left!=null) {
			node=node.left;
		}
		return node.key;
	}
	//返回最小值的节点
	private Node findMinN(Node cur) {
		Node node=cur;
		while(node.left!=null) {
			node=node.left;
		}
		return node;
	}
	//返回最大值
	public K findMax() {
		Node node=root;
		while(node.right!=null) {
			node=node.right;
		}
		return node.key;
	}
	//删除最小值
	public K removeMin() {
		K key=findMin();
		remove(key);
		return key;
	}
	//删除最大值
	public K removeMax() {
		K key=findMax();
		remove(key);
		return key;
	}
	//删除任意节点
	public void remove(K key) {
		root=remove(root,key);
	}
	//返回删除目标节点后的跟节点
	private Node remove(Node node,K key) {
		if(node==null)
			return null;
		if(key.compareTo(node.key)<0) {
			node.left=remove(node.left, key);
			return toBalance(node);
		}
		else if(key.compareTo(node.key)>0) {
			node.right=remove(node.right,key);
			return toBalance(node);
		}
		else {
			if(node.right==null) {
				Node pre=node.left;
				node.left=null;
				return pre;
			}
			if(node.left==null) {
				Node pre=node.right;
				node.right=null;
				return pre;
			}
			Node pre=findMinN(node.right);
			pre.right=remove(node.right,pre.key);
			pre.left=node.left;
			node.left=node.right=null;
			return toBalance(pre);
		}
	}
//打印AVL树
	@Override
	public String toString() {
		// TODO 自动生成的方法存根
		StringBuffer res=new StringBuffer();
		generationBSTString(root, 0, res);
		return res.toString();
	}
	private void generationBSTString(Node node,int depth,StringBuffer res) {
		if(node==null) {
			res.append(generationBSTDepth(depth)+"null\n");
			return;
		}
		res.append(generationBSTDepth(depth)+node.key+"\n");
		generationBSTString(node.left, depth+1, res);
		generationBSTString(node.right, depth+1, res);

	}
	private String generationBSTDepth(int depth) {
		StringBuffer res=new StringBuffer();
		for(int i=0;i<=depth;i++) {
			res.append("--");
		}
		return res.toString();
	}

}

一个简单的测试用例:

public class Test {
public static void main(String[] args) {
	AVLTree<Integer, Integer> tree=new AVLTree<>();
	Random random=new Random();
	//添加50以内的随机数,先输出随机数的插入顺序再输出树的结构
	for(int i=0;i<10;i++) {
		int a=random.nextInt(50);
		System.out.print(a+" ");
		tree.add(a, -1);
	}
	System.out.println();
	System.out.println(tree);

}

测试用例某一次的输出结果为:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值