文章目录
从零开始的Java学习生活(10)
在上文中,我们初步了解了什么是数组以及数组的初始化、访问方法。今天我们将继续数组的学习,了解并学会如何对数组进行增删改查等基本操作。
一、数组的遍历
(1)什么是数组遍历
数组的遍历:指的是获取数组中的每个元素。
还记得我们上节课举的军训点名的例子吗?我们继续拿来用一下。
数组的遍历可以理解为让学生依次报数(输出元素的值),来看下面这个例子;
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
}
通过前篇文章的知识,我们可以很清楚的知道,上面代码的作用是逐个输出数组里每一个元素的值。
但这么多输出语句是不是很不简洁?这时候我们就需要一个方法来简化他的写法。回顾之前的知识,我们可以很容易的想到for循环;(规律:每条打印语句唯一的区别就是数组的下标不同。下标从0开始,每次下标增1,直到数组个数-1。)
于是我们可以把代码改成下面的样子:
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
for(int i = 0; i < 5; i++) {
System.out.println(arr[i]);
}
}
仔细观察不难发现,i 的初始值 0,可以对应数组第 1 个元素的下标0,每循环一次,执行一次 i++, 可以让 i 的值增 1,这样能对应数组的每一个下标。直到 i 的值达到数组元素个数-1,即 i < 数组元素个数。
(2)数组元素个数
由于数组元素个数这么重要,所以Java提供了获取数组元素个数的的方式。
格式:数组名.length
示例:arr.length
鉴于此,上述代码可以进一步优化。
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
(3)数组遍历的通用格式
因为每个数组的元素个数,都可以通过数组名.length获得,所以任意一个数组的遍历都可以写成如下形式:
public static void main(String[] args) {
int[] 数组名 = {...};
for(int i = 0; i < 数组名.length; i++) {
数组名[i];//对 数组名[i] 进行操作
}
}
(4)数组遍历的应用
那么数组遍历在我们的编程中有什么作用呢?
最简单的就是逐个输出元素的值,然后就是可以用来逐位查找等于某一个值的元素;得到数组最大(小)值;部分元素求和、求平均值;判断数组是否相等;数组的拷贝;数组增加(删除)数据;数组排序;
我们会在下文中重点讲一下其中的增加删除元素,数组排序,这三种操作。
二、数组操作
1.数组插入数据
数组插入数据:指的是向数组中某个位置插入数据,因为数组长度不可变,因此需要保证数组足够长,能容纳下所有的数据。
- 需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。将66插入到下标为1的位置。
分析:
1. 创建一个能容纳10个元素的数组。数组的前七个数是35,22,17,41,72,29,10。
2. 将数据后移,空出位置来插入数据
即: array[7] = array[6];
array[6] = array[5];
array[5] = array[4];
array[4] = array[3];
array[3] = array[2];
array[2] = array[1];
上述过程可以使用循环实现
3. 将数据66赋值给array[1]
还是拿我们的军训队伍举例:如果有一位同学来晚了,教练让他归队。粗略的可以分成两种情况:1.在队尾2.不在队尾。在队尾的话就很简单,直接站过去就可以了;在队伍中间的话,如果想让这个同学站进去,那么原来站在那里的同学肯定要改变位置。我们让原同学往后移动一位,这时候又出现了新的位置重复,这时也要重复这个移位操作。整体上来看,就是新来的同学插入到指定位置,该位置后面的数据均依次后移一位(数组足够大)。
数组不够大的情况我会在以后专门写一篇进行说明。
上述需求完整代码如下:
public static void main(String[] args) {
int[] array = {35, 22, 17, 41, 72, 29, 10, 0, 0, 0};
for(int i = 6; i >= 1; i--) {
array[i+1] = array[i];
}
array[1] = 66;
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
2.数组数据的删除
数组删除数据:指的是删除某个下标的数据(或者删除某个指定的数据)。指定的数据被删除后,它后面的数据要前移。
- 需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。将数组下标为1的数据删除。
思路很简单,和增加反着来就可以了,直接看代码:
public static void main(String[] args) {
//需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。将数组下标为1的数据删除。
//分析:
//1. 创建一个包含10个元素的数组,数组的前7个数组是35,22,17,41,72,29,10。
//2. 将数据前移,依次覆盖数据。
// 即: array[1] = array[2];
// array[2] = array[3];
// array[3] = array[4];
// array[4] = array[5];
// array[5] = array[6];
// 上面的步骤可以用循环实现
//3. 将array[6]的值改为0
int[] array = {35, 22, 17, 41, 72, 29, 10, 0, 0, 0};
for(int i = 1; i < 6; i++) {
array[i] = array[i + 1];
}
array[6] = 0;
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
3.数组数据的排序
数组排序指的是让一堆杂乱无章的数据,按从小到大排列,或者按从大到小排列,让其有规律。这个过程就是数组排序。排序的算法很多,例如:冒泡排序,选择排序,快速排序,归并排序,插入排序等等。咱们讲一下冒泡排序和选择排序。
(1) 冒泡排序
冒泡排序:海底的气泡由于水压的作用,越深的地方气泡就越小,气泡在上浮的过程中,由于水压的减小,气泡会越来越大,到达海面的时候,气泡会最大。基于这个启发,数学家们发明了冒泡排序。
冒泡排序的思想:以从小到大排序为例。依次比较相邻的2个数据,如果前面的数据大于后面的数据,二者交换位置,一趟下来之后,最大的数据就跑到了末尾,这个数据在下一趟不再参与比较。第二趟仍然是依次比较相邻的2个数据,如果前面的数据大于后面的数据,二者交换位置,第二趟下来之后,第2大的数据就跑到了倒数第二位,同样这个数据不再参与下一趟的比较,以此类推,对于具有n个数的数组而言,进行n-1趟上述过程,就能让数组有序。
来看下面一段实现冒泡排序的代码:
public static void main(String[] args) {
//需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
//分析:
//1.创建一个数组保存上述数据
//2.使用冒泡法进行排序
//原始数据 67 42 88 16 25 3------一共6个数据,共比较5趟
//第1趟,一共比较5次
// 第1次 42 67 88 16 25 3
// 第2次 42 67 88 16 25 3
// 第3次 42 67 16 88 25 3
// 第4次 42 67 16 25 88 3
// 第5次 42 67 16 25 3 88-----88不再参与下一轮比较。第1趟找出了最大值
//第2趟,一共比较4次
// 第1次 42 67 16 25 3 88
// 第2次 42 16 67 25 3 88
// 第3次 42 16 25 67 3 88
// 第4次 42 16 25 3 67 88-----67和88不再参与下一轮比较,第2趟找出了第2大值。
//第3趟,一共比较3次
// 第1次 16 42 25 3 67 88
// 第2次 16 25 42 3 67 88
// 第3次 16 25 3 42 67 88-----42,67,88不再参与下一轮比较,第3趟找出了第3大值
//第4趟,一共比较2次
// 第1次 16 25 3 42 67 88
// 第2次 16 3 25 42 67 88-----25,42,67,88不再参与下一轮比较,第4趟找出了第4大值
//第5趟,一共比较1次
// 第1次 3 16 25 42 67 88-----全部数据有序。
int[] array = {67, 42, 88, 16, 25, 3};
for(int i = 0; i < array.length - 1; i++) {
for(int j = 0; j < array.length - 1 - i; j++) {
if(array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
冒泡排序的格式也很固定:
for(int i = 0; i < 数组名.length - 1; i++){
for(int j = 0; j < 数组名.length - 1 - i; j++){
if(数组名[j] > 数组名[j+1]){
数据类型 temp = 数组名[j];
数组名[j] = 数组名[j+1];
数组名[j+1] = temp;
}
}
}
(2) 选择排序
选择排序思想:以从小到大排序为例。第一趟,从数组中找出最小值,并记录最小值的下标,让最小值与数组下标为0的元素交换位置。第二趟,刨除数组下标为0的元素,在剩下的元素中找出最小值,并记录最小值的下标,与数组下标为1的元素交换位置。第三趟,刨除数组下标为0和1的元素,在剩下的元素中找出最小值,并记录最小值的下标,与数组下标为2的元素交换位置,以此类推,如果要对n个数排序,n-1趟即可让数组有序。
操作如下图:
代码:
public static void main(String[] args) {
//需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
//分析:
//1.创建一个数组保存上述数据
//2.定义变量index保存最小值的下标。
//3.使用选择排序法进行排序
//原始数据 67 42 88 16 25 3------一共6个数据,共比较5趟
//第1趟,一共比较5次 假定下标为0的元素是最小值。即index初始值是0
// 第1次 67 42 88 16 25 3 下标为1的和下标为index的比较,下标为1的更小,将index更新为1
// 第2次 67 42 88 16 25 3 下标为2的和下标为index的比较,下标为index比较小,不更新index
// 第3次 67 42 88 16 25 3 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第4次 67 42 88 16 25 3 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第5次 67 42 88 16 25 3 下标为5的和下标为index的比较,下标为5的更小,将index更新为5
// 第1趟结束后,最小的元素已经找到,即下标为5的元素,让下标为5的元素和下标为0的元素交换位置。
// 3 42 88 16 25 67---最小值就找出来了。最小值不再参与下一趟比较。
//第2趟,一共比较4次 假定下标为1的元素是最小值。即index初始值是1
// 第1次 3 42 88 16 25 67 下标为2的和下标为index的比较,下标为index比较小,不更新index
// 第2次 3 42 88 16 25 67 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第3次 3 42 88 16 25 67 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第4次 3 42 88 16 25 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第2趟结束后,第二小的元素已经找到,即下标为3的元素,让下标为3的元素和下标为1的元素交换位置。
// 3 16 88 42 25 67---最小值和次小值就找出来了。二者不再参与下一趟比较。
//第3趟,一共比较3次 假定下标为2的元素是最小值。即index初始值是2
// 第1次 3 16 88 42 25 67 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第2次 3 16 88 42 25 67 下标为4的和下标为index的比较,下标为4的更小,将index更新为4
// 第3次 3 16 88 42 25 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第3趟结束后,第三小的元素已经找到,即下标为4的元素,让下标为4的元素和下标为2的元素交换位置。
// 3 16 25 42 88 67---最小的3个数就找出来了。三者不再参与下一趟比较。
//第4趟,一共比较2次 假定下标为3的元素是最小值。即index初始值是3
// 第1次 3 16 25 42 88 67 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第2次 3 16 25 42 88 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第4趟结束后,第四小的元素已经找到,即下标为3的元素,让下标为3的元素和下标为3的元素交换位置。
// 3 16 25 42 88 67---最小的4个数就找出来了。四者不再参与下一趟比较。
//第5趟,一共比较1次 假定下标为4的元素是最小值。即index初始值是4
// 第1次 3 16 25 42 88 67 下标为5的和下标为index的比较,下标为5的更小,将index更新为5
// 第5趟结束后,第五小的元素已经找到,即下标为5的元素,让下标为5的元素和下标为4的元素交换位置。
// 3 16 25 42 67 88---至此,数据全部有序。
int[] array = {67, 42, 88, 16, 25, 3};
for(int i = 0; i < array.length - 1; i++) {
int index = i;
for(int j = i + 1; j < array.length; j++) {
if(array[j] < array[index]) {
index = j;
}
}
int temp = array[index];
array[index] = array[i];
array[i] = temp;
}
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
选择排序的写法很固定:
for(int i = 0; i < 数组名.length - 1; i++){
int index = i;
for(int j = i + 1; j < 数组名.length; j++){
if(数组名[j] < 数组名[index]){
index = j;
}
}
数据类型 temp = 数组名[i];
数组名[i] = 数组名[index];
数组名[index] = temp;
}
数组总结
- 数组是一个容器,用于存储数据。数组在创建的时候要确定容量,数组内部的元素类型必须相同。
- 数组的长度:数组名.length
- 数组可以动态初始化,也可以静态初始化。
- 数组的遍历,几维数组就用几层循环嵌套来遍历。
- 数组通常和循环结合使用。
- 数组元素的访问:数组名[下标] -----几维数组就要有几个下标。
- 数组的操作很多,求最值、和、平均值、查找元素、判断是否相等、拷贝、翻转、插入、删除、排序等等。
本篇内容到这里就结束了,下一次我们将简单的聊一聊Java中方法的使用,谢谢大家。
(ps:有关数组的深入内容会统一在数据结构番外中写,等我把面向对象编程写完就去写(别骂了别骂了,不是故意赶进度的 ))