一、数组的定义
1、基本概念和内存图
数组可以存放多个同一类型的数据。 数组也是一种数据类型, 是引用类型,他在内存里是这个样子的。
他是这样定义的。
定义:
int[] nums;
初始化:
nums = new int[3];
赋值:
nums[0] = 1;
nums[1] = 4;
nums[2] = 3;
// 直接定义初始化并赋值
int[] nums = {1,2,3};
// 这样写也行
int nums[] = new int[5];
int nums[] = new int[]{1,2,4,5};
// 数组有一个属性,可以获得数组的长度
nums.length
类型[] 名字 = new 类型[长度];
说说这三个步骤,如图:
三个问题:
1、数组不初始化能赋值吗?
2、初始化之后,如果不赋值,会不会有默认值?只要给你开辟了空间就一定会有默认值。
3、数组能不能越界赋值,比如长度为三,非要给第五个赋值。
2、数组的性质
结束了这个谈论,我们简单的概括一个数组的特性
- 数组一旦建立,长度不能改变。
- 每个位置只能存一个值,多了会覆盖。
- 数组创建后会有默认值:int 0, short 0, byte 0, long 0, float 0.0,double 0.0, char \u0000, boolean false, String null
- 编号从0开始,下标必须在指定范围内使用, 否则报: 下标越界异常。
- 他有个长度的属性,最后一个位置的编号是 长度-1。 0 - length -1
- 数组里边可以是基本类型,也可以是引用类型。
3、数据结构
大学里有一门课很重要,叫数据结构与算法。
数组是一种最基本的数据结构,是表的一种,是一种二维的线性表,我们以后还会接触链表,hash表等。
百度百科是这样解释线性表的:
- 线性表是最基本、最简单、也是最常用的一种数据结构。线性表*(linear list)*是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
- 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的)。
二、玩转数组
1、通循环遍历打印数组的每一个值
我们已经学习过了for循环,for循环正好能从0循环到某一个值,而这刚好可以对应我们数据的下标,写出一个优雅的循环。
我们要明确的是我的的范围是 0 ~ length -1
for (int i = 0; i < salary.length; i++) {
System.out.print(salary[i] + " ");
}
我们不妨思考一下使用while循环可以吗?
int i = 0;
while (i < nums.length){
System.out.println(nums[i]);
i++;
}
1
2
3
4
5\
大家慢慢一定要学会举一反三。
2、查找一个数组里存在的值
思路很简单,遍历每一个值,然后比较,知道遇到这个值为止。
// 定义一个变量,存放找到的目标值
int target ;
for (int i = 0; i < salary.length; i++) {
if(salary[i] == 5){
res = salary[i];
}
}
System.out.println(target);
你会发现这么写是错的,编译可能出问题:Error:(21, 28) java: 可能尚未初始化变量res;
那我们target初始化一个几呢?0吗? 万一人家最后的就是要找0,怎么办,其实巧用数组下标是个好办法。
这其实很简单,我们的目标其实是查找一下这个数字在第几个格子而已。这样的好处就是,格子不可能有负数。
我们不妨这样设计,如果找到了就获得他的下标,如果找不到就得到-1,代码可以优化如下:
int targetIndex = -1;
for (int i = 0; i < salary.length; i++) {
if(salary[i] == 9){
targetIndex = i;
}
break;
}
3、打擂台的形式找最大值
今天要比武决胜负,找出一个武功最高的当武林盟主。
1、黄蓉在台上大喊,今天我们要比武决胜负,选出一位丐帮帮主,哪位英雄好汉愿意第一个上。
2、丁春秋第一个上来,大吼,谁敢上来和我比试比试?
3、郭芙蓉上台一个排山倒海干掉了丁春秋,于是丁春秋下台,台上站的是郭芙蓉。
4、大家你来我往,一个一个上,最后站在台上的是张无忌,顺利当选。
我们的代码如下:
// 定义一个数组,存放各路英雄豪杰
int[] salary = {4,5,0,6,7,8};
// 搞一个擂台,让第0个人上来
int maxIndex = 0 ;
// 然后从第一个开始打
for (int i = 1; i < salary.length; i++) {
// 谁赢了,谁继续在台上站着
if(salary[i] > salary[maxIndex]){
maxIndex = i;
}
}
System.out.println("经过了n轮比赛得到的最大值得下标是:"+maxIndex+"。值是:"+salary[maxIndex]);
4、元素的位移
一个新的需求:
我门计划将数组中的两个元素交换位置。
int[] salary = {4,5,0,6,7,8};
salary[0] = salary[1];
salary[1] = salary[0];
我们第一次很有可能写出这样的代码。
salary[0] = salary[1]; 这句话执行完了之后 数组中 就出现了两个salary[1]了。
合适的方法是,在找一个空间,临时存一下salary[0]。
int[] salary = {4,5,0,6,7,8};
int temp = salary[0];
salary[0] = salary[1];
salary[1] = temp;
5、数组的扩容
(1)思路一:
我们一定要知道,数组本质上不能改变大小,实质上的扩容是不行的,需要使用一些手段。
画一个图吧:
// 定义原始数组
int[] nums = new int[]{3,4,6};
// 定义一个新的临时数字
int[] temp = new int[6];
// 讲原始数组的数据全部拷贝到临时数组
for (int i = 0; i < nums.length; i++) {
temp[i] = nums[i];
}
// 让原始数组的引用指向临时数组,感觉上就像原始数组被扩容了
nums = temp;
for (int i = 0; i < nums.length; i++) {
System.out.println(temp[i]);
}
创建一个等长的数组,反向放入,最后改变引用即可
int[] nums = new int[]{3,4,6};
int[] temp = new int[nums.length];
for (int i = nums.length - 1; i >= 0; i--) {
temp[i] = nums[nums.length - 1 - i];
}
nums = temp;
for (int i = 0; i < nums.length; i++) {
System.out.println(temp[i]);
}
(2)思路二:
利用交换的方式:
// 定义原始数组
int[] nums = new int[]{3,4,6};
// 交换反转
for (int i = 0; i < nums.length/2; i++) {
int temp = nums[nums.length - 1 - i];//保存
nums[nums.length - 1 - i] = nums[i];
nums[i] = temp;
}
for (int i = 0; i < nums.length; i++) {
System.out.println(nums[i]);
}
三、二维数组
二维数组使用的频率很少,但是也有一些类似的需求,比如我们开发一个围棋游戏, 棋盘就可以用二维数组来表示。 如图:
怎么定义一个数组呢?
比如: int nums[][]=new int[2][3]
在内存中二维数组张这个样子:
请用二维数组输出如下图形 :TwoDimensionalArray
int[][] nums = {{1,2,3,4,5,6},
{6,5,4,3,2,1},
{1,2,3,4,5,6}};
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();//换行
}
思考,二维数组里的每一个数组的长度一定要一样吗,如下图可以吗?
答案是可以的:
int[][] nums = {{1,4},{1,2,6},{5,6,3,2,1}};
我们还可以这样赋值:
// 这个初始化做了什么工作,这样就可以开辟空间初识化了,只不过每一个都是null
int[][] nums = new int[3][];
// 赋值
nums[0] = new int[5];
nums[1] = new int[3];
nums[2] = new int[7];
明白一个道理,初识化只要知道我需要多少空间,然后在堆内存给他分配就好了。
附加题:
写一个杨辉三角,他是这么一个三角:
- 每个数等于它上方两数之和。
- 每行数字左右对称,由1开始逐渐变大。
- 第n行的数字有n项。
- 前n行共[(1+n)n]/2 个数。
我们的输入目标:
使用二维数组打印一个 10 行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
代码实现
public class YangHui {
public static void main(String[] args) {
int max = 10;
// 分配三角形的数组
int[][] nums = new int[max + 1][];
for (int n = 0; n <= max; n++)
nums[n] = new int[n + 1];
// 填充杨辉三角
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums[i].length; j++) {
// 边边上全是1,每一行的0和length-1都是1
if (j == 0 || j == nums[i].length - 1) {
nums[i][j] = 1;
} else {
// 剩余的部分按照规律来
nums[i][j] = nums[i-1][j-1] +nums[i-1][j];
}
}
}
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums[i].length; j++) {
System.out.print(nums[i][j]+" ");
}
System.out.println();
}
}
}