六、 数组

1 数组的基本用法

数组是用来存储一组相同类型数据的数据结构,数组中的数据在内存中是连续存储的,数组属于引用类型

1)数组4要素

数组名称:合法的标识符,用来区分不同的数组

数组元素:数组中存放的数据,可以是指定的任何一种数据类型,且所有数据类型相同

元素下标:也称索引,数组中每个数据的编号,从0开始,用于访问某个具体位置的元素

元素类型:声明数组时指定的数据类型

2)2个注意点

数组中元素类型必须相同

数组一旦创建,长度不可改变,但是数组中的各个元素的值可以被改变

1.1 数组的声明

基本语法:

// 推荐写法
数据类型[] 数组变量名; 
或者
数据类型 数组变量名[]; 
int a[];
String[] b;
double c[];

// 错误写法
int a[5];

注意:Java声明数组时不能指定其长度(数组中元素的个数),而需要在数组的创建阶段来指定。

1.2 数组的初始化

1)静态初始化

在数组声明的同时,对数组元素分配内存空间并对其赋值

int[] arr = {100, 4, 56, 89, 12};
String[] nameArr = new String[]{"haha", "lisi", "san", "hehe"};

数组的长度由大扩号中元素的个数决定,长度不可改变

元素的值由程序员指定,系统不自动赋值

2)动态初始化

显式指定数组的长度,而不指定数组元素的值。

int[] arr = new int[6];

数组的长度在数组创建时显式指定

数组元素的值如果没有指定,则由系统自动赋默认值

// 默认值0
int[] a = new int[5];
System.out.println(a[0]);
// 默认值0.0
double[] d = new double[5];
System.out.println(d[1]);
// 默认值0.0
float[] f = new float[5];
System.out.println(f[1]);
// 默认值空格
char c[] = new char[4];
System.out.println(c[1]);
// 默认值0
short[] s = new short[5];
System.out.println(s[0]);
// 默认值false
boolean[] bb = new boolean[5];
System.out.println(bb[1]);
// 默认值null
String[] ss = new String[3];
System.out.println(ss[0]);

int[] arr = new int[4];
arr[0] = 1;
arr[1] = 10;
arr[2] = 100;
// 下标越界
arr[3] = 1000;

数组长度也可以通过变量赋值

int len = 10;
int[] arr = new int[len];
System.out.println(arr.length);

1.3 数组的访问

数组在声明,创建(内存中为之分配空间)后,就可以访问数组中的每个元素

1)通过下标访问当个元素

语法:arrayName[index]

index 为数组元素下标(索引),可以是整型常量或整型表达式。如a[3], b[i], c[6*i]

2)普通循环遍历访问

循环访问每个元素

int[] arr = {23, 45, 12, 6, 36};
for(int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

数组的length属性可以获取它的长度,例如:arr.length

索引值从0开始,且必须小于数组的长度,即0~n-1,否则发生数组越界异常

3)增强for循环

也可称作foreach循环

基本语法:

for(元素类型 名称 : 数组名/集合等) {
  
}
int[] arr = {23, 45, 12, 6, 36};
for(int item : arr) {
    System.out.println(item);
}

2 数组的排序

2.1 冒泡排序

原理:针对待排序的元素,从第一个元素开始,相邻的两个元素依次进行比较,选出最小或最大的元素,放在序列的结束位置

比如,我们针对待排序数据进行升序排序

第一轮比较如图所示:

第一次,23和15比较,23>15,交换

第二次,23和8比较,23>8,交换

第三次,23和34比较,23<34,不交换

第四次,34和20比较,34>20,交换

第一轮比较结束,34放到序列的最后

依此类推,再对剩余的待排序元素进行比较,5个元素经过总共四轮比较,最终可以得到升序的排序结果:

8

15

20

23

34

public void bubbleSort(int[] arr) {
    int temp = 0;//交换时使用的临时变量
    if((arr == null) || (arr.length == 0)) {
        return;
    }
    //外层循环决定比较的轮数
    for(int i = 0; i < arr.length - 1; i++) {
        //内层循环决定每轮比较的次数
        //每轮都从第一个元素开始比较
        for(int j = 0; j < arr.length - 1 - i; j++) {
            //相邻两个元素进行比较,进行升序,如果前面比后面大,交换
            if(arr[j] > arr[j + 1]) {
                 temp = arr[j];
                 arr[j] = arr[j + 1];
                 arr[j + 1] = temp;
            }
        }
    }
}

2.2 选择排序

原理:根据升序或者降序的需求,每次从待排序的元素中选出最小或最大的元素,放在序列的起始位置。

选择排序时,排序的轮数和比较的次数与待排序的元素个数相关

比如待排序的元素如下arr: 23 42 5 17 35,我们进行升序排序

使用变量index记录最小值元素的索引

1)第一轮比较:index=0

Arr[0]和42比较 ,23<42,index=0

Arr[0]和5比较,23>5,index=2

Arr[2]和17比较,5<17,index=2

Arr[2]和35比较,5<35,index=2

比较4次,找到最小值5所在索引2,将5和23交换位置

第一轮比较结束:5 42 23 17 35

红色表示待排序元素

2)第二轮比较:

Index=1

Arr[1]和23比较 ,23<42,index=2

Arr[2]和17比较,23>17,index=3

Arr[3]和35比较,17<35,index=3

比较3次,找到最小值17所在索引3,将17和42交换位置

第二轮比较结束:5 17 23 42 35

3)第三轮比较:

Index=2

Arr[2]和42比较 ,23<42,index=2

Arr[2]和35比较,23<35,index=2

比较2次,本轮不用交换

第二轮比较结束:5 17 23 42 35

4)第四轮比较:

Index=3

Arr[3]和35比较 ,42<35,index=4

比较1次,42和35交换位置

第四轮比较结束:5 17 23 35 42

四轮过后,整个比较结束,得到最终排序结果

public void selectSort(int[] arr) {
    int index=0;//最小值元素的下标
    int temp = 0;//交换时使用的临时变量
    if((arr == null) || (arr.length == 0)) {
        return;
    }
    //外层循环决定比较的轮数
    for(int i=0; i < arr.length - 1; i++) {
        index=i;
        //内层循环决定每轮比较的次数
        for(int j = i + 1; j < arr.length; j++) {
            //在无序区中找到最小数据并保存其数组下标
            if(arr[j] < arr[index]) {
                index = j;
            }
        }
        //将最小元素与本轮循环的首元素进行交换
        temp = arr[i];
        arr[i] = arr[index];
        arr[index] = temp;
    }
}

3 二维数组(了解)

数组的每个元素仍然是数组

3.1 初始化

1)动态初始化

int[][] a = new int[4][5]; // 4行5列
int[][] b = new int[2][];    // 注意:此时b[0]元素为空
b[0] = new int[6];

2)静态初始化

int[][] a = {{1}, {1, 2, 4}, {56, 6}}; // 每行的元素个数可以不同
int[][] b = new int[][]{{1, 4}, {5}};

3.2 二维数组的访问

int [][] arr = new int[][]{{4,5,6},{7,8,9}};
for(int i = 0; i < arr.length; i++){
    for(int j = 0; j < arr[i].length; j++){
        System.out.println(arr[i][j]);
    }
}

4 方法的可变参数

定义方法时,当形参个数不固定时(0-n个),可以使用可变参数来解决。

可变参数使用“…”实现,Java 编译器将可变参数转换成数组

处理可变参数必须放在形参列表的最后,它前面可以有一些其他形式的参数

返回值 方法名(参数类型... 参数名) {
}
public static void main(String[] args) {
    add();  
    add(12);    
    add(12, 13);
    int[] arr = {1, 3, 6};  
    add(arr);
}

public static void add(int... nums) {
    int result = 0;
    /*
    for (int v : nums) {
        result += v;
    }
    */
    for(int i = 0; i < nums.length; i++) {
        result += nums[i];
    }
    System.out.println(result);
}

附录

引用数据类型

基础类型的变量,在内存中,存储的是常量值

引用类型变量,在内存中存储的值比较特殊,这个值是对象的地址

值传递和引用传递

值传递和引用传递是针对方法调用时,参数的传递情况

值传递:是将实参的值复制一份给形参,形参的值相当于实参的一个副本,形参(副本)的值被改变,不会影响原来实参的值。基础类型属于值传递。

可以将值传递理解成文件的负复印,不管如何修改复印件,都不会对原件产生影响

引用传递:本质上,也是将实参的值复制一份给形参,只不过这个值比较特殊,是引用类型的对象的地址。通过形参对对象进行操作,会改变原来对象的值。

可以将引用传递理解成信用卡的副卡,主卡和副卡都可以消费同一个信用卡的money

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值