Java基础 - 节点自平衡树(Size Balanced Tree,简称SBT)

package com.yc.tree;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

public class SizeBalancedTree <T extends Comparable<T>>{
	public class Node{
		//data域:存放数据项
		T data;
		//size域:存放树的大小(节点数目)
		int size;
		Node parent;
		Node left;
		Node right;
		public Node(T data, int size, Node parent, Node left, Node right){
			this.data = data;
			this.size = size;
			this.parent = parent;
			this.left = left;
			this.right = right;
		}
		public String toString(){
			return "[data="+data+",size="+size+"]";
		}
	}
	//根节点
	private Node root;

	public Node root(){
		return root;
	}
	public SizeBalancedTree(){
		root = null;
	}
	public SizeBalancedTree(T data){
		root = new Node(data, 1, null, null, null);
	}
	/**
	 * 往根为root的树中插入data
	 * @param data
	 * @param root
	 */
	public void insert(T data){

		if(root == null){ //如果根为空
			root = new Node(data, 1, null, null, null);
		}else{
			Node current = root;
			Node parent = null;
			int result = 0;
			while(current != null){
				parent = current;
				result = data.compareTo(current.data);
				if(result > 0){
					current = current.right;
				}else{
					current = current.left;
				}
			}
			Node newNode = new Node(data, 1, parent, null, null);
			if(result > 0){
				parent.right = newNode;
			}else{
				parent.left = newNode;
			}

			ancestorAdd1(newNode);

			maintain(newNode);
		}
	}
	private void ancestorAdd1(Node node){
		Node current = node;
		while(current.parent != null){
			current.parent.size += 1;
			current = current.parent;
		}
	}
	private void ancestorminu1(Node node){
		Node current = node;
		while(current.parent != null){
			current.parent.size -= 1;
			current = current.parent;
		}
	}
	private boolean trueOrFalse(Node node){
		Node current = node;
		while(current != null){
			if(current == root.left){
				return false;
			}else if(current == root.right){
				return true;
			}
			current = current.parent;
		}

		return false;
	}
	private void maintain(Node node) { //node为新添加的节点
		if(root == node.parent){
			return;
		}else{
			maintainHelp(root, trueOrFalse(node));
		}

	}
	private void maintainHelp(Node node, boolean flag){ //传过来的node为新添加的节点
		if(node != null){
			/*Node t = node;
			Node l = t.left;
			Node r = t.right;*/
			if(!flag && node.left != null){ //左边
				if((node.right == null && node.left.left != null ) || (node.left.left != null && node.left.left.size > node.right.size)){ //case1
					right_rot(node);
				}
				else if((node.right == null && node.left.right != null ) || (node.left.right != null && node.left.right.size > node.right.size)){//case2
					left_rot(node.left);
					right_rot(node);
				}else{
					return;
				}
				maintainHelp(node.left, false);
				maintainHelp(node.right, true);
				maintainHelp(node, false);
				maintainHelp(node, true);
			}else if(flag && node.right != null){ //右边
				if((node.left == null && node.right.left != null ) || (node.right.left != null && node.right.left.size > node.left.size)){ //case2*
					right_rot(node.right);
					left_rot(node);
				}
				else if((node.left == null && node.right.right != null ) || (node.right.right != null && node.right.right.size > node.left.size)){//case1*
					left_rot(node);
				}else{
					return;
				}
				maintainHelp(node.left, false);
				maintainHelp(node.right, true);
				maintainHelp(node, false);
				maintainHelp(node, true);
			}
		}
	}
	/**
	 * 从根为node的树中删除数据元素为data的节点
	 * @param node
	 * @param data
	 */
	public void remove(Node node, T data){
		Node del = find(data);
		if(del != null){
			boolean what = trueOrFalse(del);
			if(del.left == null && del.right == null){
				if(del == root){
					root = null;
				}else{
					ancestorminu1(del);
					if(del == del.parent.left){
						del.parent.left = null;
					}else{
						del.parent.right = null;
					}
					del.parent = null;
					maintainHelp(root, what);
				}
			}else if(del.right != null && del.left == null){
				//因为已经平衡,所以要删除的节点del有且仅有一个右子节点
				if(root == del){
					root = del.right;
					del.right.parent = null;
					del.right = null;
				}else{
					ancestorminu1(del);
					if(del == del.parent.left){
						del.parent.left = del.right;
					}else{
						del.parent.right = del.right;
					}
					del.right.parent = del.parent;
					del.parent = del.right = null;
					maintainHelp(root, what);
				}
			}else if(del.left != null && del.right == null){
				//因为已经平衡,所以要删除的节点del有且仅有一个左子节点
				if(root == del){
					root = del.left;
					del.left.parent = null;
					del.left = null;
				}else{
					ancestorminu1(del);
					if(del == del.parent.left){
						del.parent.left = del.left;
					}else{
						del.parent.right = del.left;
					}
					del.left.parent = del.parent;
					del.parent = del.left = null;
					maintainHelp(root, what);
				}
			}else{ //左右子树都不为空
				Node preOfDel = pre(del, data);
				del.data = preOfDel.data;
				ancestorminu1(preOfDel);
				preOfDel.parent.left = preOfDel.left;
				if(preOfDel.left != null){
					preOfDel.left.parent = preOfDel.parent;
				}
				preOfDel.parent = preOfDel.left = null;
				maintainHelp(root, what);
			}
				
		}else{
			return;
		}
			
	}
	/**
	 * 在树中查找键值为data的结点
	 * @param data
	 * @return
	 */
	public Node find(T data){
		Node current = root;
		if(root == null){
			return null;
		}else{
			int result;
			while(current != null){
				result = data.compareTo(current.data);
				if(result > 0){
					current = current.right;
				}else if(result < 0){
					current = current.left;
				}else{
					return current;
				}
			}
		}
		return null;
	}
	/**
	 * 在树中查找排名为k的节点(其实为了更好地操作,我觉得可以在每个节点中存放两个域
	 * lsize和rsize,分别存放该节点的左子树节点数量和右子树节点数量,但更耗内存)
	 * @param node
	 * @param k
	 * @return
	 */
	public Node select(Node node, int k){

		if(root == null){
			try {
				throw new Exception("该树为空");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else if(root.size < k){
			try {
				throw new Exception("该节点不存在一个排名为"+k+"的节点,但存在一个最大排名为"+root.size+"的节点");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else{
			if(node != null){
				int result;
				if(node.left != null){
					result = node.left.size + 1;
					if(result == k){
						return node;
					}else if(result < k){
						return select(node.right, k - result);
					}else{
						return select(node.left, k);
					}
				}else if(node.right != null){
					if(k == 1){
						return node;
					}else{
						return select(node.right, k - 1);
					}
				}else{
					return node;
				}
			}
		}
		return null;
	}
	//最大值
	public T minData(){
		return select(root, 1).data;
	}
	//最小值
	public T maxData(){
		return select(root, this.root().size).data;
	}
	//这里考虑到了要查看排名的数据元素不在树中
	public int rank(Node node, T data){
		Node p = find(data);
		T m = minData();
		return data.compareTo(m) < 0 ? 1 : (p == null ? cRank(node, data) + 1 : cRank(node, data));
	}
	//返回以node为根的树中元素值为data的排名
	private int cRank(Node node, T data){
		if(node != null){
			int result = data.compareTo(node.data);
			if(node.left != null && node.right != null){
				if(result < 0){
					return cRank(node.left, data);
				}else if(result > 0){
					return cRank(node.left, data) + cRank(node.right, data) + 1;
				}
				return node.left.size + 1;

			}else if(node.right != null && node.left == null){
				if(result < 0){
					return 0;
				}else if(result > 0){
					return cRank(node.right, data) + 1;
				}
				return 1;
			}else if(node.left != null && node.right == null){
				if(result < 0){
					return cRank(node.left, data);
				}else if(result > 0){
					return cRank(node.left, data) + 1;
				}

				return cRank(node.left, data) + 1;


			}else{
				if(result < 0){
					return 0;
				}else if(result > 0){
					return 1;
				}
				return 1;
			}
		}
		return 0;
	}
	//以node节点为根某数据元素的前驱
	public Node pre(Node node, T data){
		Node current = node;
		Node preNode = null;
		int result;
		while(current != null){
			result = data.compareTo(current.data);
			/*if(result == 0){
				return current;
			}else*/ if(result > 0){
				preNode = current;
				current = current.right;
			}else{
				current = current.left;
			}
		}
		return preNode;
	}
	//以node节点为根某数据元素的后继
	public Node succ(Node node, T data){
		Node current = node;
		Node preNode = null;
		int result;
		while(current != null){
			result = data.compareTo(current.data);
			/*if(result == 0){
				return current;
			}else */if(result < 0){
				preNode = current;
				current = current.left;
			}else{
				current = current.right;
			}
		}
		return preNode;
	}
	/**
	 * 右旋(x/y才是关键)
	 * @param x
	 * 				│				│
	 * 				x				y
	 * 				││     -> 		││ 
	 * 			 y──┘└─γ		 α──┘└─x
	 * 		    ││				   	   ││
	 * 		  α─┘└─β				 β─┘└─γ
	 * 
	 */
	private void right_rot(Node x){
		Node y = x.left;
		y.parent = x.parent;
		if(x.parent != null){
			if(x == x.parent.left){
				x.parent.left = y;
			}else{
				x.parent.right = y;
			}
		}
		x.left = y.right;
		if(y.right != null){
			y.right.parent = x;
		}
		y.right = x;
		x.parent = y;

		y.size = x.size;
		x.size = (y.left == null ? y.size - 0 - 1 : y.size - y.left.size - 1);

		if(root == x){
			root = y;
		}
	}
	/**
	 * 左旋(x/y才是关键)
	 * @param x
	 * 				│				│	
	 * 				x				y
	 * 				││     -> 		││ 
	 * 			 α──┘└─y		 x──┘└─γ
	 * 				  ││		││
	 * 				β─┘└─γ	  α─┘└─β
	 */
	private void left_rot(Node x){
		Node y = x.right;
		y.parent = x.parent;
		if(x.parent != null){
			if(x == x.parent.left){
				x.parent.left = y;
			}else{
				x.parent.right = y;
			}
		}
		x.right = y.left;
		if(y.left != null){
			y.left.parent = x;
		}
		y.left = x;
		x.parent = y;

		y.size = x.size;
		x.size = (y.right == null ? y.size - 0 - 1 : y.size - y.right.size - 1);

		if(root == x){
			root = y;
		}
	}
	//广度优先遍历
	public List<Node> breadthFirstSearch(){
		return cBreadthFirstSearch(root);
	}
	private List<Node> cBreadthFirstSearch(Node node) {
		List<Node> nodes = new ArrayList<Node>();
		Deque<Node> deque = new ArrayDeque<Node>();
		if(node != null){
			deque.offer(node);
		}
		while(!deque.isEmpty()){
			Node tmp = deque.poll();
			nodes.add(tmp);
			if(tmp.left != null){
				deque.offer(tmp.left);
			}
			if(tmp.right != null){
				deque.offer(tmp.right);
			}
		}
		return nodes;
	}
	public static void main(String[] args) {
		SizeBalancedTree<Integer> tree = new SizeBalancedTree<Integer>();
		tree.insert(30);
		tree.insert(20);
		System.out.println( tree.select(tree.root(), 1) );
		tree.insert(40);
		tree.insert(10);
		tree.insert(26);
		tree.insert(35);
		tree.insert(45);
		tree.insert(8);
		tree.insert(15);
		tree.insert(23);
		tree.insert(32);
		tree.insert(27);
		tree.insert(37);
		tree.insert(21);
		tree.insert(24);
		System.out.println( tree.breadthFirstSearch());
		tree.insert(29);
		System.out.println( tree.breadthFirstSearch());

		System.out.println( "树中排名第14的元素为:"+tree.select(tree.root(), 14) );
		System.out.println();
		System.out.println( "37的排名为:"+tree.rank(tree.root(),37));
		System.out.println();
		System.out.println( "37的前驱为:"+tree.pre(tree.root(), 37));
		System.out.println( "36的后继为:"+tree.succ(tree.root(), 36));
		
		tree.remove(tree.root(), 26);
		System.out.println( tree.breadthFirstSearch());
	}
}

测试结果为:

[data=20,size=1]
[[data=30,size=15], [data=20,size=9], [data=40,size=5], [data=10,size=3], [data=26,size=5], [data=35,size=3], [data=45,size=1], [data=8,size=1], [data=15,size=1], [data=23,size=3], [data=27,size=1], [data=32,size=1], [data=37,size=1], [data=21,size=1], [data=24,size=1]]
[[data=26,size=16], [data=20,size=7], [data=35,size=8], [data=10,size=3], [data=23,size=3], [data=30,size=4], [data=40,size=3], [data=8,size=1], [data=15,size=1], [data=21,size=1], [data=24,size=1], [data=27,size=2], [data=32,size=1], [data=37,size=1], [data=45,size=1], [data=29,size=1]]
树中排名第14的元素为:[data=37,size=1]

37的排名为:14

37的前驱为:[data=35,size=8]
36的后继为:[data=37,size=1]
[[data=24,size=15], [data=20,size=6], [data=35,size=8], [data=10,size=3], [data=23,size=2], [data=30,size=4], [data=40,size=3], [data=8,size=1], [data=15,size=1], [data=24,size=1], [data=27,size=2], [data=32,size=1], [data=37,size=1], [data=45,size=1], [data=29,size=1]]


另附两篇大神满的文章:  

Size Balanced Tree(SBT树)整理

【平衡二叉树】SBT学习笔记

这里有C++和Python源码地址:

节点大小平衡树((Size Balanced Tree, c++和python源码)



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值