数组++sum++java_java数组

数组

数组概述

数组的定义

数组是相同类型数据的有序集合。

数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。

其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

数组声明创建

首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:

dataType[] arrayRefVar; //首选的手法

dataType arrayRefVar[]; //效果相同,但不是首选方法

Java语言使用new操作符来创建数组,语法如下:

dataType[] arrayRefVar = new dataType[arraySize];

数组元素是通过索引方向访问的,数组索引从0开始。

获取数组长度:arrays.length

示例:

public class Demo01 {

public static void main(String[] args) {

//变量的类型 变量的名字 = 变量的值

//数组类型

int[] nums; //1.定义:声明数组

int nums2[];//声明数组的第二种方式

nums = new int[10]; //2.创建

//给数组赋值

nums[0] = 1;

nums[1] = 2;

nums[2] = 3;

nums[3] = 4;

nums[4] = 5;

nums[5] = 6;

nums[6] = 7;

nums[7] = 8;

nums[8] = 9;

nums[9] = 10;

//计算所有元素的和

int sum = 0;

for (int i = 0; i < nums.length; i++) {//nums,length为数组长度

sum+=nums[i];//通过i索引

}

System.out.println("总和为"+sum);//打印结果

}

}

数组使用

Java内存分析

Java内存这里讲三个:堆,栈方法区

如图:

4cf1e80715125c9d05e4e3e55af036bb.png

所以,在数组创建的那个示例里面过程是这样的

声明数组在栈里面创建array。

然后创建数组在堆里面开辟空间。

输入数值。

5f2d2e52ecc4a295097b4ec7e2a12afe.png

两种初始化

除了new初始化以外还有静态初始化:创建+赋值,定义之后不可改变

int[] a={1,2,3,5,6};//初始化数组a

动态初始化:包含默认初始化

int[] b = new int[10];

b[0] = 10;//动态初始化数组b

数组的的默认初始化

数组是引用类型,他的元素相当于类的实例变量,因此数组一经分配空间,其中每个元素也被按照实例变量同样的方式被隐式初始化,默认值为0或者null。

数组的四个基本特点:

其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。

其元素必须是相同类型,不允许出现混合类型。

数组中的元素可以是任何数据类型,包括基本类型和引用类型。

数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

数组边界

下标合法区间:[0,length-1],如果越界就会报错;

public class Demo02 {

public static void main(String[] args) {

int[] a=new int[2];

System.out.println(a[2]);

}

}

上面的代码会报错:错误名字叫ArrayIndexOutOfBoundsException:数组下标越界异常

小结:

数组是相同数据类型(数据类型可以为任意类型)的有序集合数组也是对象。

数组元素相当于对象的成员变量

数组长度的确定的,不可变的。如果越界,则报:ArraylndexOutofBounds

数组具体使用:

For-Each循环

增强for循环:

public class Demo04 {

public static void main(String[] args) {

int[] arrays = {1,2,3,4,5};//创建一个数组

//没有下标,增强for循环,注意:这里无法修改数组里面内容

for (int array : arrays) {

System.out.println(array);

}

}

}

普通for循环:这里用三个案例的例子来演示

public class Demo03 {

public static void main(String[] args) {

int[] arrays = {1,2,3,4,5};

//打印全部数组元素

for (int i = 0; i < arrays.length; i++) {

System.out.println(arrays[i]);

}

//===============================================

System.out.println("================================");

//计算所有元素的和

int sum =0;

for (int i = 0; i < arrays.length; i++) {

sum +=arrays[i];

}

System.out.println("sum="+sum);

//=================================================

System.out.println("====================================");

//查找最大元素

int max =arrays[0];

for (int i = 0; i

if(arrays[i]>max){

max = arrays[i];

}

}

System.out.println("max="+max);

}

}

数组作方法入参

这里写一个打印数组的示例:

public class Demo04 {

public static void main(String[] args) {

int[] arrays = {1,2,3,4,5};

print(arrays);

}

//打印数组方法

public static void print(int[] a){

for (int i = 0; i < a.length; i++) {

System.out.print(a[i]+" ");

}

System.out.println();

}

}

400ae88f85135647b77149c200ead145.png

数组作为返回值

这里用反转数组作为示例演示数组怎么作为返回值

public class Demo04 {

public static void main(String[] args) {

int[] arrays = {1,2,3,4,5};

arrays = reverse(arrays);

for (int array : arrays) {

System.out.println(array);

}

}

//反转数组方法

public static int[] reverse(int[] a){

int[] result = new int[a.length];//返回结果的数组

for (int i = 0,j=0; i < a.length; i++,j++) {

result[j] = a[a.length-1-i];

}

return result;

}

84e82d1a225de02e1480d38717ea278e.png

多维数组

多维数组可以看成数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。

二维数组:

int a[][] =new int[2][5];

上面的二维数组a可以堪称一个两行五列的数组。

就像这样:

648a155ba347d6a74b29d5c5ba5a198f.png

示例:

public class Demo05 {

public static void main(String[] args) {

//创建一个二维数组

int[][] array ={{1,2},{2,3},{3,4},{4,5}};

//打印二维数组

for (int i = 0; i < array.length; i++) {

for (int j = 0; j < array[i].length; j++) {//根据定义可知,二维数组每一个元素都是一个一维数组,所以这里用array[i].length来表示长度

System.out.println(array[i][j]);

}

}

}

}

8281b1470a22ec13cfdfc359e1ba6b6e.png

多维数组可以参照二维数组,就是大括号里面再嵌套更多的大括号,这里是Java上的多维,不是指现实中的多维,这是两个概念。

Arrays类

数组的工具类java.util.Arrays

由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。

Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意:是"不用”而不是“不能")

具有以下常用功能:

给数组赋值:通过fill方法。

对数组排序:通过sort方法,按升序。

比较数组:通过equals方法比较数组中元素值是否相等。

查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

这些都是工具,建议看这篇文章的时候自己去用,这里不再写示例。

冒泡排序

冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。

import java.util.Arrays;

//冒泡排序

public class Demo07 {

public static void main(String[] args) {

int[] a={25,2545,78,7,5,45,56,78,9,2,4};

sort(a);//调用我们的排序方法后

System.out.println(Arrays.toString(a));

}

//冒泡排序方法

//1.比较数组中,两个相邻的元素,如果第一个数比第二个大,我们就交换他们的位置

//2.每一次比较,都会产生一个最大,或者最小的数字;

//3.下一轮可以减少一次排序;

//4.一次循环,直到结束。

public static int[] sort(int[] array){

//临时变量

int temp = 0;

//外层循环,判断我们这个走多少次

for (int i = 0; i < array.length-1; i++) {

//内层循环,比较两个数字大小如果第一个数字比第二个打,则交换位置

for (int j = 0; j < array.length-i-1; j++) {

if(array[j+1]>array[j]){

temp = array[j];

array[j] = array[j+1];

array[j+1] = temp;

}

}

}

return array;

}

}

结果如图

818a0ccd80403efa56fad33ccff35387.png

我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。

稀疏数组

当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。稀疏数组的处理方式是:

记录数组一共有几行几列,有多少个不同值

把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模如下图:左边是原始数组,右边是稀疏数组

17e96f030027b8b4f707a89ed129a0fa.png

图中我们可以看到稀疏数组中[0]表示原数组的行列数以及有效值的个数,后面[1],[2]依次表示有效值的位置以及值为多少。

好了,我们就那上面的图作为案例:

首先是创建案例中的数组

//创建一个案例中的数组

int[][] array1 = new int[6][7];

//赋值有效值

array1[0][3] = 22;

array1[0][6] = 15;

array1[1][1] = 11;

array1[1][5] = 17;

array1[2][3] = -6;

array1[3][5] = 39;

array1[4][0] = 91;

array1[5][2] = 28;

//打印案例数组

for (int[] ints : array1) {

for (int anInt : ints) {

System.out.print(anInt+"\t");

}

System.out.println();//换行

}

结果如图

14e2e960cb889c9799ef3204fdd9779a.png

​ 然后我们写一个将案例数组转化为稀疏数组的方法:

//稀疏数组转换

public static int[][] sparse(int[][] array){

//获取数组中有效值个数

int sum = 0;

for (int i = 0; i < array.length; i++) {

for (int j = 0; j < array[i].length; j++) {

if(array[i][j]!=0){

sum++;

}

}

}

System.out.println("有效值个数:"+sum);

//创建稀疏数组

int[][] Sarray = new int[sum+1][3];//因为稀疏数组只有行列值三列,所以后面是3,行为有效个数+1

//给稀疏数组赋值

Sarray[0][0] = array.length;

Sarray[0][1] = array[0].length;

Sarray[0][2] = sum;

int count = 0; //计数

for (int i = 0; i < array.length; i++) {

for (int j = 0; j < array[i].length; j++) {

if(array[i][j]!=0){

count++;

Sarray[count][0] = i;

Sarray[count][1] = j;

Sarray[count][2] = array[i][j];

}

}

}

//返回稀疏数组

return Sarray;

}

转化之后结果如图:

fd7adb4f41c8121fac095f471dc1e41d.png

这样,数组转化为稀疏数组就完成了,当然我们还要会还原数组

//稀疏数组还原

public static int[][] recovery(int[][] Sarray){

//创建还原后的数组

int[][] array = new int[Sarray[0][0]][Sarray[0][1]];

//赋值阶段

for (int i = 0; i < Sarray.length-1; i++) {

int x = Sarray[i+1][0];//行

int y = Sarray[i+1][1];//列

array[x][y] = Sarray[i+1][2];//值

}

return array;//返回

}

结果为:

1a2057378f7fc6c53e317b1726b2a804.png

本来想单独写主函数,但是为了观看方便,我把整篇代码放在这里

//稀疏数组案例

public class Demo08 {

public static void main(String[] args) {

//创建一个案例中的数组

int[][] array1 = new int[6][7];

//赋值有效值

array1[0][3] = 22;

array1[0][6] = 15;

array1[1][1] = 11;

array1[1][5] = 17;

array1[2][3] = -6;

array1[3][5] = 39;

array1[4][0] = 91;

array1[5][2] = 28;

//打印案例数组

for (int[] ints : array1) {

for (int anInt : ints) {

System.out.print(anInt+"\t");

}

System.out.println();//换行

}

//获取稀疏数组

int[][] array2 = sparse(array1);

System.out.println("====================");//分割线

//打印稀疏数组

System.out.println("打印稀疏数组:");

for (int[] ints : array2) {

for (int anInt : ints) {

System.out.print(anInt+"\t");

}

System.out.println();//换行

}

//稀疏数组还原

System.out.println("==================");//分割线

int[][] array3 = recovery(array2);

//打印还原的数组

System.out.println("打印还原的数组");

for (int[] ints : array3) {

for (int anInt : ints) {

System.out.print(anInt+"\t");

}

System.out.println();//换行

}

}

//稀疏数组转换

public static int[][] sparse(int[][] array){

//获取数组中有效值个数

int sum = 0;

for (int i = 0; i < array.length; i++) {

for (int j = 0; j < array[i].length; j++) {

if(array[i][j]!=0){

sum++;

}

}

}

System.out.println("有效值个数:"+sum);

//创建稀疏数组

int[][] Sarray = new int[sum+1][3];//因为稀疏数组只有行列值三列,所以后面是3,行为有效个数+1

//给稀疏数组赋值

Sarray[0][0] = array.length;

Sarray[0][1] = array[0].length;

Sarray[0][2] = sum;

int count = 0; //计数

for (int i = 0; i < array.length; i++) {

for (int j = 0; j < array[i].length; j++) {

if(array[i][j]!=0){

count++;

Sarray[count][0] = i;

Sarray[count][1] = j;

Sarray[count][2] = array[i][j];

}

}

}

//返回稀疏数组

return Sarray;

}

//稀疏数组还原

public static int[][] recovery(int[][] Sarray){

//创建还原后的数组

int[][] array = new int[Sarray[0][0]][Sarray[0][1]];

//赋值阶段

for (int i = 0; i < Sarray.length-1; i++) {

int x = Sarray[i+1][0];//行

int y = Sarray[i+1][1];//列

array[x][y] = Sarray[i+1][2];//值

}

return array;//返回

}

}

本篇文章为个人的学习日记,欢迎各位大佬指正!

6bc29801896ec2dba8088d58d1522215.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
树状数组(Fenwick Tree)是一种用于快速维护数组前缀和的数据结构。它可以在 $O(\log n)$ 的时间内完成单点修改和前缀查询操作,比线段树更加简洁高效。 下面是 Java 实现的树状数组详解: 首先,在 Java 中我们需要使用数组来表示树状数组,如下: ``` int[] tree; ``` 接着,我们需要实现两个基本操作:单点修改和前缀查询。 单点修改的实现如下: ``` void update(int index, int value) { while (index < tree.length) { tree[index] += value; index += index & -index; } } ``` 该函数的参数 `index` 表示要修改的位置,`value` 表示修改的值。在函数内部,我们使用了一个 `while` 循环不断向上更新树状数组中相应的节点,直到到达根节点为止。具体来说,我们首先将 `tree[index]` 加上 `value`,然后将 `index` 加上其最后一位为 1 的二进制数,这样就可以更新其父节点了。例如,当 `index` 为 6 时,其二进制表示为 110,最后一位为 2^1,加上后变为 111,即 7,这样就可以更新节点 7 了。 前缀查询的实现如下: ``` int query(int index) { int sum = 0; while (index > 0) { sum += tree[index]; index -= index & -index; } return sum; } ``` 该函数的参数 `index` 表示要查询的前缀的结束位置,即查询 $[1, index]$ 的和。在函数内部,我们同样使用了一个 `while` 循环不断向前查询树状数组中相应的节点,直到到达 0 为止。具体来说,我们首先将 `sum` 加上 `tree[index]`,然后将 `index` 减去其最后一位为 1 的二进制数,这样就可以查询其前一个节点了。例如,当 `index` 为 6 时,其二进制表示为 110,最后一位为 2^1,减去后变为 100,即 4,这样就可以查询节点 4 的值了。 最后,我们还需要初始化树状数组,将其全部置为 0。初始化的实现如下: ``` void init(int[] nums) { tree = new int[nums.length + 1]; for (int i = 1; i <= nums.length; i++) { update(i, nums[i - 1]); } } ``` 该函数的参数 `nums` 表示初始数组的值。在函数内部,我们首先创建一个长度为 `nums.length + 1` 的数组 `tree`,然后逐个将 `nums` 中的元素插入到树状数组中。具体来说,我们调用 `update(i, nums[i - 1])` 来将 `nums[i - 1]` 插入到树状数组的第 `i` 个位置。 到此为止,我们就完成了树状数组的实现。可以看到,树状数组的代码比线段树要简洁很多,而且效率也更高。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值