Day10——数组
1、数组
1. 数组概述:
数组是,相同类型数据的有序集合。
通常使用数组下标来区分或指定每一个数组元素,数组下标从0开始(假设一个数组有4个数,那么数组下标就是0、1、2、3)。
使用数组避免了定义多个变量的麻烦,并且会让程序变的简单。
2. 数组的声明、创建
声明、创建数组格式:
声明:
dataType[] array; //声明一个dataType类型的数组,名称为array
dataType array[]; //与1同义,常用于C、C++语言
创建:
array = new dataType[length];//创建array数组长度为length
声明+创建:
dataType[] array = new dataType[length];
//声明并创建一个dataType类型的数组,名称为array,长度为length
【例1】:
声明:
int[] nums;//声明整型数组,亦可写作 int nums[]; 后者为C、C++写法
创建:
nums = new int[10];//创建长度为10的整型数组(即数组元素有十个)
声明+创建:
int[] nums = new int[10];// 声明 + 创建一个长度为10的整型数组
获取数组长度:数组名.length
数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 (数组名.length-1)。
3. 内存分析
Java内存分析:
- 声明数组,数组会被放在栈中,此时数组并没有被真正的创建
- 创建数组时,数组被放入堆中,此时数组元素还未进行初始化,基本数据类型的数组元素默认值为0,String数组默值认为null
除了用new关键字来创建数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值。
int[] a = {1,2,3};
2. 动态初始化: 即声明数组后,用new创建数组,并维数组赋值的操作(分开进行)。
3. 数组的默认初始化:
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实 例变量同样的方式被隐式初始化。基本数据类型的数组元素默认值为0,String数组默值认为null。
### 数组的使用
-
For-Each循环:
JDK 1.5 引进了一种新的循环类型,被称为 For-Each 循环或者加强型循环,它能在不使用下标的情况下 遍历数组。
语法格式:
type array = new type[length];
//声明并创建一个type型,array数组,长度为length
for(type element: array){//没有数组下标
System.out.println(element);//输出element数组的元素
}
在IDEA中【缩写】nums.for = for (type i : nums){}
其中,nums为数组名,type为数组类型,i为任意名称、代指数组中元素。
-
数组作为方法的参数:
【例2】写一个输出数组的方法printArray
public static void printArray(int[] arrays){
for( i = 0; i < arrays.length; i++ ){
System.out.println(arrays[i]+" ")
}
}
或者写做:
public static void printArray(int[] arrays){
for(int i: array){
System.out.println(i);
}
}
-
数组作为返回值:
【例3】写一个方法反转数组,并让数组作为返回值
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
int[] a = printRe(arrays);
//5.反转arrays数组,赋值给a数组
for(int i: a){
System.out.print(i+" ");
}//6.For-Each循环打印出反转后的数组
}
public static int[] printRe(int[] arrays){
//1.返回值为整型数组,所以printRe为数组类型方法,用int[]
int[] result = new int[arrays.length];
//2.创建一个,与arrays数组长度相等的数组result用于储存反转后的数组元素
for (int i = 0; i < arrays.length; i++){
result[arrays.length-i-1] = arrays[i];
}//3.反转数组元素
return result;//4.返回反转后的数组
}
若题目条件没有限制,上述代码可简化为:
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
reserve(arrays);//调用方法reserve()
}
public static void reserve(int[] arrays){
//此方法没有返回值,因使用void类型
for (int i = arrays.length - 1; i >= 0; i--) {
System.out.print(arrays[i]+" ");
}//反转数组并输出
}
2、二维数组
二维数组是特殊的一维数组,其每一个元素都是一个一维数组。
-
二维数组的动态初始化:
type[][] typeName = new type[length1][length2]
//二维数组类型为type,名称为typeName,有length1行,length2列
【例】
int[][] nums = new int[3][5]
//声明并创建了int类型的二维数组nums,该数组有3行5列
//该二维数组元素从nums[0][0]到nums[2][4]共3*5=15个数
-
获取数组长度:
nums.length获取的长度是 行数,nums[i].lenght获取的长度是第i行的元素个数
上述例子中,nums.length = 5;nums[i].lenght = 3。
-
二维数组的输出:
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
System.out.print(arrays[i][j]+" ");
}
System.out.println();//输入完一行就换行
}
3、Arrays类
数组的工具类java.util.Arrays,使用之前需要导包即import java.util.Arrays;
输出数组元素:通过 toString 方法,打印数组。
对数组排序:通过 sort 方法,按升序。
【例4】
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] a = {1,9,8,3,5,2,7};
System.out.println(Arrays.toString(a));//打印数组
Arrays.sort(a);//对数组排序
System.out.println(Arrays.toString(a));
}
}//[1, 9, 8, 3, 5, 2, 7]
//[1, 2, 3, 5, 7, 8, 9]
4、冒泡排序
对于一组数,依次比较相邻两数的大小(1和2,2和3,3和4...),并将较大(小)的数交换到后面,重复执行该组数的(个数-1)次后,就能得到一组顺序(逆序)排列的数列。
这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),故名“冒泡排序”。
【例5】代码实现:排序一组数
public static void sort(int[] arrays){
for (int i = 0; i < arrays.length-1; i++) {
for (int j = 0; j < arrays.length-1; j++) {
if( arrays[j] > arrays[j+1]){
int x = arrays[j];
arrays[j] = arrays[j+1];
arrays[j+1] = x;//5~7行,交换j和j+1的数字的位置
}
}
}
}//内循环用于比较和调位置,外循环用于重复
【思考】以上代码,对于任何数组,都要执行( length-1 )^2次,对于本身就是顺序排列(或者调位次数很少就能完成排序)的数组,这样显然很浪费时间。
因此可以引入判断标志flag,在外循环里声明int flag=0,并在内循环的 if 中改变flag的值(flag=1),这样可以判断:
1、如果flag值改变,说明经历了if中的调位(调换位置)过程,说明正在排序,
2、反之,如果flag的值没有改变,说明经历了完整的内循环(从头到尾的相邻比较),并没有出现调位过程,即,数组已经排序完毕,可以提前推出排序过程,从而减少不必要的比较过程。
这段确实很难理解,我已经尽力描述的通俗易懂了。。。
代码修改后:
public static void sort(int[] arrays){
for (int i = 0; i < arrays.length-1; i++) {
int flag = 0;
for (int j = 0; j < arrays.length-1; j++) {
if( arrays[j] > arrays[j+1]){
int x = arrays[j];
arrays[j] = arrays[j+1];
arrays[j+1] = x;
flag = 1;
}
}
if(flag == 0){//在内循环完成后判断是否改变了flag的值
break;//如果flag没有改变,即数组已经排序完毕,退出外循环
}
}
}
稀疏数组(扩展)
稀疏数组