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
*
* */
数状数组的原理与应用
最新推荐文章于 2022-10-11 15:01:52 发布