Chapter5 数组、排序和查找
一、数组
1.必要性
传统的定义不同变量的方法既浪费内存空间又浪费精力
数组可以存放多个同一类型的数据,数组也是一种数据类型,是引用类型
数组就是一组数据
2.案例
养鸡场养鸡
public class Array01 {
//编写一个main方法
public static void main(String[] args) {
//一个养鸡场有6只鸡,它们体重分别是3kg,5kg,1kg3.4kg,2kg,50kg
//请问这6只鸡总体重是多少?平均体重是多少
//定义一个数组
double[] hens = {3, 5, 1, 3.4, 2, 50};//double类型的数组 数组名是hens
//可以使用数组名.length表示数组长度/大小
//数组的遍历
double totalWeight = 0;
for(int i = 0; i < hens.length; i++) {
//System.out.println("第" + i+1 + "个元素的值是" + hens[i]);//使用for循环得到各个元素的值
totalWeight += hens[i];
}
System.out.println("总体重 = " + totalWeight +
"平均体重 = " + (totalWeight / hens.length));
}
}
3.数组的使用
1.动态初始化
1.法1
数组定义
数据类型 数组名[] = new 数据类型[大小]
e.g:
int a[] = new int [5];
数组的引用
数组(访问/使用/获取数组元素)
数组名[下标/索引] 要访问a数组第二个元素—>a[1]
import java.util.Scanner;
public class Array01 {
//编写一个main方法
public static void main(String[] args) {
double[] scores = new double[5];
Scanner scanner = new Scanner(System.in);
for(int i = 0; i < scores.length; i++) {
System.out.println("请输入第" + (i+1) + "个成绩");
scores[i] = scanner.nextDouble();
}
//再次遍历输出
for(int i = 0; i < scores.length; i++) {
System.out.println("第" + (i+1) + "的成绩为" + scores[i]);
}
}
}
2.法2
数组声明
不会给数组分配具体的空间,自动赋值NULL
数据类型 数组名[]; 数据类型[] 数组名
e.g: int a[]; int [] a;
创建数组
这时才会真正的分配空间
a = new int [10];
2.静态初始化
当具体元素的值已知时,且元素个数不多,使用静态初始化
int a[] = {2, 5, 6, 7, 8, 89, 90, 34, 56};
4.数组使用细节
- 数组是多个相同类型数据的组合,实现对这些数据的统一管理
- 数组中的元素可以使任何数据类型,包括基本类型和引用类型,但是不能混用
- 数组创建后,如果没有赋值,有默认值
int 0, short 0, byte 0, long 0, float 0.0, double 0.0,char \u0000, boolean false, String null; - 使用数组的步骤:1.声明数组并开辟空间;2.给数组各个元素赋值;3.使用数组
- 数组的下标是从0开始的
- 数组下标必须在指定范围内使用,编译无错,运行时报异常:下标越界异常
所以最大数组下标是(数组长度-1) - 数组属于引用类型,数组型数据是对象(object)
5.数组使用练习
1.打印大写字母表
public class ArrayExercise01 {
//编写一个main方法
public static void main(String[] args) {
/*
创建一个char类型的26个元素的数组,分别放置'A'-'Z'
使用for循环访问所有元素并打印出来
*/
char[] c = new char[26];
for(int i = 0; i < c.length; i++) {
c[i] = (char)('A' + i);// 'A' + i 是int类型 此处需要强制类型转换
}
for(int i = 0; i < 26; i++) {//控制输出结构,以便结果更美观
System.out.print(c[i]);
if(i % 5 == 0 && i != 0) {
System.out.println("");
}
}
}
}
2.寻找最大值及其下标
public class ArrayExercise02 {
//编写一个main方法
public static void main(String[] args) {
/*
求出一个数组int[] 最大值(4,-1,9,10,23),
并得到对应的下标
*/
int[] a = {4,-1,9,10,23};
int max = a[0];//记录最大值
int flag = 0;//记录最大值索引
for(int i = 1 ; i < a.length ; i++) {
if(max < a[i]) {
max = a[i];
flag = i;
}
}
System.out.println("最大值是" + max + " 其下标是" + flag);
}
}
6.数组赋值机制
-
基本数据类型赋值,这个值就是具体的数据,而且互不影响
int n1 = 2; int n2 = n1; 即如案例,将n2换成其他值时,不会影响原来n1的值
赋值方式是值拷贝 -
数组在默认情况下是引用传递,赋的值是地址
赋值方式是引用赋值int[] arr1 = {1, 2, 3}; int[] arr2 = arr1; arr2[0] = 10; for(int i = 0; i < arr1.length; i++) { System.out.print(arr1[i] + " ");//输出 10 2 3 }
3.值传递(拷贝)和引用传递(地址拷贝)区别
int n1 = 2; int n2 = n1;
//值传递相当于直接在栈空间里开辟两个内存,然后直接将n1的值拷贝一份赋给n2
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;
arr2[0] = 10;
//引用传递相当于在栈区开辟一个空间存放一个指向堆区中三个元素的一个空间,即
//栈区的所用空间存放的是堆区空间的地址
7.数组拷贝
public class ArrayCopy {
//编写一个main方法
public static void main(String[] args) {
//编写代码,实现数组拷贝
//将int[] arr1 = {10, 20, 30};拷贝到数组arr2数组,要求数据空间独立
int[] arr1 = {10, 20, 30};
//int[] arr2 = arr1;行不通,arr1和arr2所指向的空间都是同一个
//创建一个新的数组arr2,在堆区开辟新的数据
//大小保证和arr1相同
int[] arr2 = new int[arr1.length];
//遍历arr1,把每个元素拷贝到相应为止
for(int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
//以示区别,改动数组第一个元素,保证打印的是单独空间的arr2;
arr2[0] = 100;
for(int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i] + " ");//100 20 30
}
}
}
8.数组反转
e.g: arr {11, 22, 33, 44, 55, 66} –>{66, 55, 44, 33, 22, 11}
法1:
public class ArrayReverse {
//编写一个main方法
public static void main(String[] args) {
//实现数组元素内容的反转
int[] arr = {11, 22, 33, 44, 55, 66};
/*
1.把arr[0] arr[5]交换 {66, 22, 33, 44, 55, 11}
2.把arr[1] arr[4]交换 {66, 55, 33, 44, 22, 11}
3.把arr[2] arr[3]交换 {66, 55, 44, 33, 22, 11}
*/
int temp = 0;//temp变量不定在循环中,否则需要重复定义,浪费内存空间
int len = arr.length;//计算数组长度
for(int i = 0; i < len / 2; i++) {//交换的次数需要看规律得出
temp = arr[i];
arr[i] = arr[len - i - 1];
arr[len - i - 1] = temp;
}
for(int i = 0; i < len; i++) {
System.out.print(arr[i] + " ");
}
}
}
法二:
public class ArrayReverse {
//编写一个main方法
public static void main(String[] args) {
//实现数组元素内容的反转
int[] arr = {11, 22, 33, 44, 55, 66};
/*
1.逆序遍历arr
2.顺序赋值arr2
*/
int[] arr2 = new int[arr.length];
int len = arr.length;//计算数组长度
for(int i = len - 1,j = 0; i >= 0; i--, j++) {//交换的次数需要看规律得出
arr2[j] = arr[i];
}
arr = arr2;
//原来的数据空间不被使用,会被回收
for(int i = 0; i < len; i++) {
System.out.print(arr[i] + " ");
}
}
}
9.数组扩容
实现动态给数组添加元素的效果,实现对数组扩容
e.g: 1.原始数组使用静态分配 int[] arr = {1, 2, 3};
2.增加的元素4,直接放在数组的最后 arr = {1, 2, 3, 4}
3.用户可以通过下面方法来决定是否继续添加,添加成功,是否继续?
1.实现单个元素的添加
public class ArrayAdd {
//实现单个元素的添加
//编写一个main方法
public static void main(String[] args) {
int[] arr = {1, 2, 3};//原数组
//定义一个新数组,数组个数比与数组多一个
int[] arrNew = new int[arr.length + 1];
//遍历原数组,将每个原数组个数赋给新数组
for(int i = 0; i < arr.length; i++) {
arrNew[i] = arr[i];
}
//新增数组元素置于新数组最后
arrNew[arrNew.length - 1] = 4;
arr = arrNew;//将原数组指向新数组,相当于原数组得到扩展,先前的空间被舍弃
for(int i = 0; i < arr.length; i++) {//打印出扩展后的数组元素
System.out.print(arr[i] + "\t");
}
}
}
2.实现动态的增加数组元素
import java.util.Scanner;
public class ArrayAdd {
//实现元素的动态添加
//编写一个main方法
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arr = {1, 2, 3};//原数组
do {
//定义一个新数组,数组个数比与数组多一个
int[] arrNew = new int[arr.length + 1];
//遍历原数组,将每个原数组个数赋给新数组
for(int i = 0; i < arr.length; i++) {
arrNew[i] = arr[i];
}
System.out.println("请输入你想要添加的元素:");
int addNum = scanner.nextInt();
//新增数组元素置于新数组最后
arrNew[arrNew.length - 1] = addNum;
arr = arrNew;//将原数组指向新数组,相当于原数组得到扩展,先前的空间被舍弃
for(int i = 0; i < arr.length; i++) {//打印出扩展后的数组元素
System.out.print(arr[i] + "\t");
}
System.out.println("是否继续添加?(y/n)");
char key = scanner.next().charAt(0);
if(key == 'n') {//如果输入N提前结束
break;
}
}while(true);
System.out.println("你退出了添加");
}
}
10.数组删除
删除数组中最后一个元素
import java.util.Scanner;
public class ArrayDelete {
//实现单个元素的添加
//编写一个main方法
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arr = {1, 2, 3};//原数组
do {
//定义一个新数组,数组个数比与数组少一个
int[] arrNew = new int[arr.length - 1];
//遍历原数组,将每个原数组个数赋给新数组
for(int i = 0; i < arrNew.length; i++) {
arrNew[i] = arr[i];
}
arr = arrNew;//将原数组指向新数组,相当于原数组实现了 删除最后一个元素 功能
for(int i = 0; i < arr.length; i++) {//打印出删除最后单个元素的新数组
System.out.print(arr[i] + "\t");
}
System.out.println("是否继续删除?(y/n)");
char key = scanner.next().charAt(0);
if(key == 'n') {//如果输入N提前结束
break;
}
}while(true);
System.out.println("你退出了删除");
}
}
二、排序
排序是将多个数据,依据指定的顺序进行排列的过程
1.排序的分类
1.内部排序:
指将需要处理的所有数据都加载到内衬布存储器中进行排序。包括(交换式排序法、选择式排序法和插入式排序法);
2.外部排序法:
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。
2.冒泡排序法(Bubble Sorting)
1.基本思想
通过对排序序列从后到前(从下标较大元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素组件从前移向后部,就如水底的气泡一样逐渐上冒
2.案例
1.单个循环实现
public class BubbleSort {
//编写一个main方法
public static void main(String[] args) {
//五个无序:24,69,80,57,13
//使用冒泡排序法使其排列成一个从小到大的有序数列
/*
第1轮排序:目标是把最大数放在最后
第1次比较 {24, 69, 80, 57, 13}
第2次比较 {24, 69, 80, 57, 13}
第3次比较 {24, 69, 57, 80, 13}
第4次比较 {24, 69, 57, 13, 80}
第2轮排序:目标是把第二大的数放在倒数第二位
第1次比较:{24, 69, 57, 13, 80}
第2次比较:{24, 57, 69, 13, 80}
第3次比较:{24, 57, 13, 69, 80}
第3轮比较:目标是把第三大的数放在倒数第三位
第1次比较:{24, 57, 13, 69, 80}
第2次比较:{24, 13, 57, 69, 80}
第4轮比较:目标把第四大的数放在倒数第四位
第1次比较:{13, 24, 57, 69, 80}
五个元素
四轮排序(外层循环)
每一轮确定一个数,第1轮确定第1大的数,第2抡确定第2大的数,依次类推
当进行比较时,前面的数大于后面的数就交换
每轮比较次数在减少 4 -> 3 -> 2 -> 1
*/
int[] a = {24, 69, 80, 57, 13};
int temp = 0;
for(int j = 0; j < 4; j++) {//第1轮循环
//如果前面的数大于后面的数就交换
if(a[j] > a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
System.out.println("==第1轮==");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
for(int j = 0; j < 3; j++) {//第2轮循环
//如果前面的数大于后面的数就交换
if(a[j] > a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
System.out.println("\n==第2轮==");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
for(int j = 0; j < 2; j++) {//第3轮循环
//如果前面的数大于后面的数就交换
if(a[j] > a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
System.out.println("\n==第3轮==");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
for(int j = 0; j < 1; j++) {//第4轮循环
//如果前面的数大于后面的数就交换
if(a[j] > a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
System.out.println("\n==第4轮==");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
}
}
2.使用外层循环
public class BubbleSort {
//编写一个main方法
public static void main(String[] args) {
//五个无序:24,69,80,57,13
//使用冒泡排序法使其排列成一个从小到大的有序数列
/*
第1轮排序:目标是把最大数放在最后
第1次比较 {24, 69, 80, 57, 13}
第2次比较 {24, 69, 80, 57, 13}
第3次比较 {24, 69, 57, 80, 13}
第4次比较 {24, 69, 57, 13, 80}
第2轮排序:目标是把第二大的数放在倒数第二位
第1次比较:{24, 69, 57, 13, 80}
第2次比较:{24, 57, 69, 13, 80}
第3次比较:{24, 57, 13, 69, 80}
第3轮比较:目标是把第三大的数放在倒数第三位
第1次比较:{24, 57, 13, 69, 80}
第2次比较:{24, 13, 57, 69, 80}
第4轮比较:目标把第四大的数放在倒数第四位
第1次比较:{13, 24, 57, 69, 80}
五个元素
四轮排序(外层循环)
每一轮确定一个数,第1轮确定第1大的数,第2抡确定第2大的数,依次类推
当进行比较时,前面的数大于后面的数就交换
每轮比较次数在减少 4 -> 3 -> 2 -> 1
*/
int[] a = {24, 69, 80, 57, 13};
int temp = 0;
for(int i = 0; i < 4; i++) {//外层循环4次 i 控制几轮排序
for(int j = 0; j < 4 - i; j++) {//j 控制比较次数
//(4-i)次
//如果前面的数大于后面的数就交换
if(a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
System.out.println("\n==第" + (i + 1) + "轮==");
for(int j = 0; j < a.length; j++) {
System.out.print(a[j] + "\t");
}
}
}
}
3.先死后活
先前的方法只能对数组个数为5的数组进行排序,为了适应更多的元素的数组,发现规律:
排序次数 = 数组个数-1
public class BubbleSort {
//编写一个main方法
public static void main(String[] args) {
//五个无序:24,69,80,57,13
//使用冒泡排序法使其排列成一个从小到大的有序数列
/*
第1轮排序:目标是把最大数放在最后
第1次比较 {24, 69, 80, 57, 13}
第2次比较 {24, 69, 80, 57, 13}
第3次比较 {24, 69, 57, 80, 13}
第4次比较 {24, 69, 57, 13, 80}
第2轮排序:目标是把第二大的数放在倒数第二位
第1次比较:{24, 69, 57, 13, 80}
第2次比较:{24, 57, 69, 13, 80}
第3次比较:{24, 57, 13, 69, 80}
第3轮比较:目标是把第三大的数放在倒数第三位
第1次比较:{24, 57, 13, 69, 80}
第2次比较:{24, 13, 57, 69, 80}
第4轮比较:目标把第四大的数放在倒数第四位
第1次比较:{13, 24, 57, 69, 80}
五个元素
四轮排序(外层循环)
每一轮确定一个数,第1轮确定第1大的数,第2抡确定第2大的数,依次类推
当进行比较时,前面的数大于后面的数就交换
每轮比较次数在减少 4 -> 3 -> 2 -> 1
*/
int[] a = {24, 69, 80, 57, 13};
int temp = 0;
//将原先的i < 4 改成数组个数 - 1 适应更多情况
for(int i = 0; i < a.length - 1; i++) {//外层循环4次 i 控制几轮排序
for(int j = 0; j < a.length - 1 - i; j++) {//j 控制比较次数
//(4-i)次
//如果前面的数大于后面的数就交换
if(a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
System.out.println("\n==第" + (i + 1) + "轮==");
for(int j = 0; j < a.length; j++) {
System.out.print(a[j] + "\t");
}
}
}
}
输出效果和原先一样,适应更多的数组
三、查找
1.顺序查找
有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:
从键盘中任意输入一个名称,判断数列中是否包含次名称(顺序查找)
要求:如果找到,就提示找到,并给出下标
import java.util.Scanner;
public class SeqSearch {
//编写一个main方法
public static void main(String[] args) {
/*
有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:
从键盘中任意输入一个名称,判断数列中是否包含次名称(顺序查找)
要求:如果找到,就提示找到,并给出下标
*/
String[] kings = {"白眉鹰王","金毛狮王","紫衫龙王","青翼蝠王"};
Scanner scanner = new Scanner(System.in);
System.out.println("请输入名字:");
String king = scanner.next();
int index = -1;//设置一个索引,以便区分是否找到
for(int i = 0; i < kings.length; i++) {
if(kings[i].equals(king)) {
System.out.println("找到了,下标是:" + i);
index = i;//索引值改变,以便区分
break;
}
}
if(index == -1) {//索引值未改变表示没找到
System.out.println("未找到");
}
}
}
2.二分查找
import java.util.Scanner;
public class BinarySearch {
//编写一个main方法
public static void main(String[] args) {
int [] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Scanner scanner = new Scanner(System.in);
int input = scanner.nextInt();
int right = a.length - 1;//右坐标
int left = 0;//左坐标
while (left <= right){
int mid = (right + left) / 2;//中间数的坐标
if (a[mid] > k) {
right = mid - 1;
} else if (a[mid] < k) {
left = mid + 1;
} else {//如果查找的数与中间数相等
printf("找到了,下标是:%d\n", mid);
break;
}
}
if (left > right) {//若没有找到
printf("NULL\n");
}
}
}
四、多维数组(二维数组)
1.定义及案例
二维数组
从定义上看是 int[][];
原来的一维数组的每个元素都是一维数组,就构成了二维数组
案例:
public class TwoDimentionalArray {
//编写一个main方法
public static void main(String[] args) {
//使用二维数组打印
//0 0 0 0 0 0
//0 0 1 0 0 0
//0 2 0 3 0 0
//0 0 0 0 0 0
int[][] arr = {{0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0}, {0, 2, 0, 3, 0, 0}, {0, 0, 0, 0, 0, 0}};
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();
}
}
}
关于二维数组的关键概念
- System.out.println(“二维数组的个数 = ” + arr.length);//4
即二维数组有四个一维数组作为数组元素- 二维数组的每个元素都是一维数组,所以如果需要得到每个一维数组的值
还需要再次遍历- 如果我们要访问第(i+1)个一维数组的第(j+1)个值,需要用 arr[i][j]
e.g:访问 {{0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 2, 0, 3, 0, 0},
{0, 0, 0, 0, 0, 0}};
中元素 3
它是第3个以为数组的第4个值 需要用 arr[2][3]
2.二维数组的使用
1.动态初始化(直接定义使用)
- 类型[][] 数组名 = new 类型[大小][大小]
e.g:int a[][] = new int[2][3];
2 表示这个二维数组中有2个一维数组
3 表示每个一维数组中有3个元素 - 二维数组在内存的存在方式
2.动态初始化(先声明再定义)
先声明:类型 数组名[][];
再定义(开辟空间):数组名 = new 类型[大小][大小]
赋值(有默认值,int类默认值是0)
3.动态初始化(列数不确定)
一维数组的个数可以不相同
public class TwoDimentionalArray02 {
//编写一个main方法
public static void main(String[] args) {
/*
动态开辟一个数组
i = 0 : 1
i = 1 : 2 2
i = 2 : 3 3 3
一个有三个一维数组,每个一维数组元素不一样
*/
int[][] arr = new int [3][];
//创建二维数组,一共3个一维数组,但每个一维数组都没开辟空间
for(int i = 0; i < arr.length; i++) {
//给每个一维数组开辟空间
//如果没有开辟空间,arr[i]是null
//给一维数组开辟空间
arr[i] = new int [i + 1];
//遍历一维数组,并给一维数组的每个元素赋值
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = i + 1;
}
}
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();
}
}
}
4.静态初始化
- 定义:类型 数组名[][] = {{值1,值2…},{值1,值2…},{值1,值2…}}
- 直接使用(固定方式访问)
3.二维数组使用
1.二维数组求和
public class TwoDimentionalArrayExercise01 {
//编写一个main方法
public static void main(String[] args) {
/*
int arr[][] = {{4,6},{1,4,5,7},{-2}};
遍历该二维数组,并得到和
*/
int arr[][] = {{4,6},{1,4,5,7},{-2}};
int sum = 0;
for(int i = 0; i < arr.length; i++) {
//遍历每个一维数组
for(int j = 0; j < arr[i].length; j++) {
sum += arr[i][j];
}
}
System.out.println("sum = " + sum);
}
}
2.杨辉三角打印
public class YangHui {
//编写一个main方法
public static void main(String[] args) {
/*
打印出10行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
......
第一行有1个元素,第n行有n个元素
每一行的第一个元素和最后一个元素都是1
从第三行开始,对于非第一个和最后一个元素的值,
arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
*/
int[][] yangHui = new int[10][];
for(int i = 0; i < yangHui.length; i++) {//遍历yangHui的每个元素
//给每个一维数组开辟空间
yangHui[i] = new int[i + 1];//第1行1个元素,第2行2个元素
//给每个一维数组赋值
for(int j = 0; j < yangHui[i].length; j++) {
if(j == 0 || j == yangHui[i].length - 1) {
yangHui[i][j] = 1;
} else {//中间元素
yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
}
}
}
//输出杨辉三角
for(int i = 0; i < yangHui.length; i++) {
for(int j = 0; j < yangHui[i].length; j++) {
System.out.print(yangHui[i][j] + " ");
}
System.out.println();//输出完每行元素后换行
}
}
}
4.二维数组使用细节
1.一维数组声明方式
int[] x 或者 int x[];
2.二维数组声明方式
int[][] y 或者 int[] y[] 或者int y[][]
3.二维数组实质
二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不同
e.g:
map [][] = {{1, 2}, {3, 4, 5}};
map[0]是由两个元素组成的一维数组
map[1]是由三个元素组成的一维数组也就是列数不等的二维数组
五、本章练习
1.声明: int[]x,y[];以下允许通过编译的是(BE)
x 是int类型的一维数组 y 是int类型的二维数组
A.x[0] = y; × int[][] -> int
B.y[0] = x; √ int[]->int[]
C.y[0][0] = x; × int[]->int
D.x[0][0] = y; × int[][] -> int
E.y[0][0] = x[0]; √ int -> int
F.x = y; × int[][] ->int[]
2.下面数组定义正确的有(BD)
A.String strs[] = {‘a’,’b’,’c’}; × char-> String
B.String[] strs = {“a”,”b”,”c”};
C.String[] strs = new String{“a”,”b”,”c”};//需要括号
D.String str[] = new String[]{“a”,”b”,”c”}; // √
E.String[] strs = new String[3]{“a”,”b”,”c”}; × 括号中不要填写具体的值
3.写出结果
String foo = “blue”; Boolean[] bar = new boolean[2]; if(bar[0]) { foo = “green” } System.out.println(foo);//blue
4.以下代码输出结果为
int num = 1; while(num < 10) { System.out.println(num); if(num > 5) { break; } num += 2; }//1 3 5 7
5.已知有一个升序数组,要求插入一个元素,该数组顺序依然是升序(扩容+定位)
{10, 12, 45, 90} 添加23后 ,数组为
{10, 12, 23, 45, 90}
public class Homework01 { //编写一个main方法 public static void main(String[] args) { /* 已知有一个升序数组,要求插入一个元素,该数组顺序依然是升序 {10, 12, 45, 90} 添加23后 ,数组为 {10, 12, 23, 45, 90} */ /* 1.先确定添加的数应该插入到哪个索引 2.然后扩容 */ int[] arr = {10, 12, 45, 90};//定义原数组 int insertNum = 111;//-1 111 依旧可以保证数组的有序性 int index = -1;//index就是要插入的位置 //遍历arr数组 如果 insertNum <= arr[i] , 那么i就是需要插入的位置 //使用index 保留位置 index = i; //如果遍历完成,还未发现 insertNum <= arr[i] //则 index = arr.length 即添加到arr最后 for(int i = 0; i < arr.length; i++) { if(insertNum <= arr[i]) { index = i; break;//找到位置后就退出 } } //通过index判断是否找到位置 即插入的数是一个很大的数 if(index == -1) {//还未找到位置 index = arr.length; } //扩容 int[] arrNew = new int[arr.length + 1]; //将arr元素拷贝到arrNew,并跳过index位置 for(int i = 0, j = 0; i < arrNew.length; i++) {、 //i控制新数组arrNew下标,j控制原数组arr下标 if(i != index) {//可以把arr元素拷贝到arrNew arrNew[i] = arr[j]; j++; //如果i是等于index,走的是else语句, //即j++没有实现,而i++在for循环条件中,所以仍然实现 //这样就实现了最终的跳过index位置拷贝元素 } else {//i就是要插入的数 arrNew[i] = insertNum; } } //让arrNew指向arr arr = arrNew; System.out.println("=====插入后,arr元素情况====="); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
6.随机生成10个整数(1-100)保留到数组,并倒序打印以及求平均值,求最大值和最大值下标,并查找里面是否有8
public class Homework02 { //编写一个main方法 public static void main(String[] args) { /* 随机生成10个整数(1-100)保留到数组 并倒序打印以及求平均值,求最大值和最大值下标 并查找里面是否有8 */ int[] arr = new int[10]; for(int i = 0; i < arr.length; i++) { arr[i] = (int)(Math.random()*100)+1;//随机生成一个(0-100)整数 } double sum = 0; int max = arr[0]; int maxIndex = -1,index = -1; for(int i = 0; i < arr.length; i++) {//计算总和以及找最大值及其下标 sum += arr[i]; if(arr[i] > max) { max = arr[i]; maxIndex = i; } if(arr[i] == 8) {//查找8是否在数组内 index = i; } System.out.print(arr[i] + " ");//正序打印一遍以便观察 } System.out.println(); for(int i = arr.length - 1; i >= 0; i--) {//逆序输出 System.out.print(arr[i] + " "); } System.out.println(); System.out.println("ave = " + sum / arr.length); System.out.println("最大值为" + max + "下标为" + maxIndex); if(index2 != -1) { System.out.println("找到了,8的下标为" + index); } else { System.out.println("找不到8"); } } }
7.试写出以下代码的打印结果
char[] arr1 = {'a','z','b','c'}; char[] arr2 = arr1; arr1[2] = '溪'; for(int i = 0; i < arr2.length; i++) { System.out.println(arr1[i] + "," + arr2[i]); }// a,a // 2,2 // 溪,溪 // c,c
arr1[2]将‘b’改成了‘溪’
而arr1和arr2又指向同一块内存空间
故最后输出的结果是相同的
8.冒泡排序法
public class Homework03 { //编写一个main方法 public static void main(String[] args) { //冒泡排序 //要求从小到大 int[] arr = {20, -1, 89, 2, 890, 7}; int temp = 0;//辅助交换元素 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; } } } System.out.println("===== 排序后 ====="); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }