数状数组的原理与应用

 
package arithmetic;
import java.util.*;
public class TreeArray {
	
	public static int[] conver(int array[])
	{
		int tree[] = new int[array.length];
		Arrays.fill(tree,0);
		for(int i=1;i<=array.length;i++)
			for(int j=i;j>=(i-lowbit(i)+1);j--)   //也可以写成for(int j=i;j>i-lowbit(i);j--)
				tree[i-1]+=array[j-1];
			return tree;
		
	}
	public static int lowbit(int x)   //  求 2^k
	{
		return x&(x^(x-1));
	}
	
	/*
	 * 				数状数组的应用-
	 * 				求一个数组的前N 项各  		Sum(array,n);
	 * 
	 * */
	public static  int arraySum(int []array,int n)
	{
		int sum=0;
		int tree[] = conver(array);  //求出该数组的数状数组
		while(n>=0)
		{
			sum+=tree[n];			//tree[n] 表示从array[n] 到 array[lowbit(n+1)]项的和
			n-=lowbit(n+1);		//因为数组数组的 索引是从0开始的,所以这里要加1
		}
		return sum;
	}
	/*
	 * 				数状数组应用二
	 * 				对原数组修改,其数组数组对应也要做出修改
	 * */
	
	public static int [] add(int []array,int n,int data)//将array 数组中的第n 个元素加上data 后,求出其数组状数组
	{
		int tree[] = conver(array);
		while(n<=array.length)
		{
			tree[n]+=data;
			n+=lowbit(n+1);  //只要改变其上一级相关的值(之所以加1 就因为数头数组的索引是从0开始的),弄清数组数组中结点与上级结点之间的关系
								//因为你只改变了一个结点,其上级结点也要改变  tree[n] 的上级结点为 tree[n+lowbit(n)]
		}
		return tree;
	}
	public static void main(String args[])
	{
		int array[]= {1,2,3,4,5,6,7,8};
		System.out.println(Arrays.toString(conver(array)));
		int tree[] = add(array,0,1);
		System.out.println(Arrays.toString(tree));
	}
}
/*
 * 
 * 						数状数组
 * 				有一个数组 Array={1,2,3,4,5,6,7,8};
 * 				用一个树的结点来表示这个数组内某几项的和,而树的结点是有规律的
 * 
 *     			C[] 表示该树的结点的序号
 *     			C[n] =Array[n-2^k+1]+.....+Array[n];	(2^k 表示2的K次方,K是表示N的二进制位末尾0的个数,有一个公式来计算 2^k)
 *     																	那就是 n&(n^(n-1)) 中期的^ 表示异或
 *     			所以上面的公式也就是 C[n] = Array[n-n&(n^(n-1)]+.....+Array[n];
 *     
 *     
 *     
 *     			在操作数组与数状数组之间的关系时,要弄清两点
 *     			1.	数状数组中,结点与其上级结点的关系。因为你要修改,一个结点的改变,其相连的上级结点也要改变 tree[n] 上级结点 tree[n+lowbit(n)]
 *     			2. 	弄清数状数组中结点与其数组中结点的关系。数组数组中的一个结点是数组中一个多个连接的结点的和  tree[n]=array[n-lowbit(n)+1]+.....+array[n]
 * 
 * 				参考:
 * 					http://dongxicheng.org/structure/binary_indexed_tree/
 * 					http://old.blog.edu.cn/user3/Newpoo/archives/2007/1712628.shtml
 * 
 * */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值