编程小技巧
- index=-1; 如果数组中有这个元素, 将index设为下标值
本章难题
- 已知有个升序的数组, 要求插入一个元素, 该数组顺序依次是升序, 比如 [10, 12, 45, 90], 添加23 后, 数组为 [10, 12, 23 ,45, 90].
注意事项
- 在普通的for循环中, 如果我们要循环100次, 我们会这么写: for (int i = 1; i <= 100; i++) {}, 即循环变量从1开始
- 普通循环, 不涉及数组, 我的习惯是循环变量起始值是1
- 如果要循环数组, 循环arr.length次, 我们这样写: for (int i = 0; i < arr.length; i++) {}, 循环变量从0开始
- 因为数组的下标是从0开始的, 同时小于等于号写成小于号
需求: 一个养鸡场有6只鸡, 它们的体重分别是3kg, 5kg, 1kg, 3.4kg, 2kg, 50kg. 请问这六只鸡的总体重是多少? 平均体重是多少? 请编写一个程序. Array01.java
思路: 定义6个变量, 加起来, 求出总体重, 再求出平均体重
//数组的引出
public class Array01 {
//编写一个main方法
public static void main(String[] args) {
/*
它们的体重分别是3kg, 5kg, 1kg, 3.4kg, 2kg, 50kg.
请问这六只鸡的总体重是多少? 平均体重是多少? 请编写一个程序.
思路分析
1.定义六个变量 double, 求和 得到总体重
2.平均体重 = 总体重 / 6
3.分析传统实现的方式问题. 6 => 600 => 5666
4.引出新的技术 -> 使用数组来解决
*/
double hen1 = 3;
double hen2 = 5;
double hen3 = 1;
double hen4 = 3.4;
double hen5 = 2;
double hen6 = 50;
double totalWeight = hen1 + hen2 + hen3 + hen4 + hen5 + hen6;
double avgWeight = totalWeight / 6;
System.out.println("总体重=" + totalWeight + " 平均体重=" + avgWeight);
}
}
●数组介绍
数组可以存放多个同一类型的数据. 数组也是一种数据类型, 是引用类型.
数(数据)组(一组), 即: 数组就是一组数据
●数组快速入门 Array01.java
比如, 我们可以用数组来解决上一个问题. 体验
//数组的引出
public class Array01 {
//编写一个main方法
public static void main(String[] args) {
/*
它们的体重分别是3kg, 5kg, 1kg, 3.4kg, 2kg, 50kg.
请问这六只鸡的总体重是多少? 平均体重是多少? 请编写一个程序.
思路分析
比如, 我们可以用数组来解决上一个问题. => 体验
*/
//定义一个数组
//1.double[] 表示 是double类型的数组, 数组名 hens
//2.{3, 5, 1, 3.4, 2, 50} 表示数组的值/元素, 依次表示数组的第几个元素
double[] hens = {3, 5, 1, 3.4, 2, 50, 7.8};
//遍历数组得到数组的所有元素的和, 使用for
//解读
//1.我们可以通过 hens[下标] 来访问数组的元素.
// 下标是从0开始编号的 比如第一个元素就是 hens[0]
// 第二个元素就是 hens[1], 依此类推
//2.通过for就可以循环地访问 数组的元素/值
//3.使用一个变量 totalWeight 将各个元素累积
System.out.println("===使用数组解决===");
//可以通过 数组名.length 得到数组的大小/长度
System.out.println("数组的长度=" + hens.length);
double totalWeight = 0;
for(int i = 0; i < hens.length; i++) {
// System.out.println("第" + (i+1) + "个元素的值=" + hens[i]);
totalWeight += hens[i];
}
System.out.println("总体重=" + totalWeight + " 平均体重=" + (totalWeight / hens.length));
}
}
●使用方式1 - 动态初始化
√ 数组的定义
数组类型 数组名[] = new 数组类型[大小]
int a[] = new int[5]; //创建了一个数组, 名字a, 存放5个int
说明: 这是定义数组的一种方法. 画出数组内存图
√ 数组的引用(使用/访问/获取数组元素)
数组名[下标/索引/index] 比如: 你要使用a数组的第3个数 a[2]
数组的下标从 0 开始
√ 快速入门案例 Array02.java
import java.util.Scanner;
public class Array02 {
//编写一个main方法
public static void main(String[] args) {
//演示 数据类型 数组名[] = new 数据类型[大小]
//循环输入5个成绩, 保存到double数组, 并输出
//步骤
//1.创建一个 double 数组, 大小5
double[] scores = new double[5];
//2.循环输入
// scores.length 表示数组的大小/长度
// 创建Scanner对象, 接收用户输入
Scanner myScanner = new Scanner(System.in);
for(int i = 0; i < scores.length; i++) {
System.out.print("请输入第" + (i+1) + "个元素的值: ");
scores[i] = myScanner.nextDouble();
}
//3.循环输出, 再次遍历数组
System.out.println("===当前数组的元素/值的情况如下===");
for(int i = 0; i < scores.length; i++) {
System.out.print("第" + (i+1) + "个元素的值=" + scores[i]);
}
}
}
●使用方式2 - 动态初始化
√ 先声明数组
语法: 数组类型 数组名[]; 也可以 数组类型[] 数组名;
int a[]; 或者 int[] a;
√ 创建数组
语法: 数组名 = new 数组类型[大小]
a = new int[10];
√ 案例演示 [前面修改即可]
import java.util.Scanner;
public class Array02 {
//编写一个main方法
public static void main(String[] args) {
//演示 数据类型 数组名[] = new 数据类型[大小]
//循环输入5个成绩, 保存到double数组, 并输出
//步骤
//1.创建一个 double 数组, 大小5
// (1) 第一种动态分配方式
// double[] scores = new double[5];
// (2) 第2种动态分配方式 先声明数组, 再 new 分配空间
double[] scores;//声明数组, 这时 scores 是 null
// scores = new double[5];// 分配内存空间, 可以存放数据
//2.循环输入
// scores.length 表示数组的大小/长度
// 创建Scanner对象, 接收用户输入
Scanner myScanner = new Scanner(System.in);
for(int i = 0; i < scores.length; i++) {
System.out.print("请输入第" + (i+1) + "个元素的值: ");
scores[i] = myScanner.nextDouble();
}
//3.循环输出, 再次遍历数组
System.out.println("===当前数组的元素/值的情况如下===");
for(int i = 0; i < scores.length; i++) {
System.out.print("第" + (i+1) + "个元素的值=" + scores[i]);
}
}
}
●使用方式3 - 静态初始化
√ 初始化数组
语法: 数据类型[] 数组名 = {元素值, 元素值…}
int a[] = {1,2,3,4,5,6,7,8}, 如果知道数组有多少元素. 具体值
上面的用法相当于: int[] a = new int[9]; a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; a[4] = 5; a[5] = 6; a[6] = 7; a[7] = 8; a[8] = 9;
●快速入门案例 [养鸡场]
案例 Array01.java
前面学过
double[] hens = {3, 5, 1, 3.4, 2, 50};
等价
double[] hens = new double[6];
hens[0] = 3; hens[1] = 5; hens[2] = 1; hens[3] = 3.4; hens[4] = 2; hens[5] = 50;
ArrayDetail.java
1.数组是多个相同类型数据的组合, 实现对这些数据的统一管理
2.数组中的元素可以是任意类型数据, 包括基本类型和引用类型, 但是不能混用
3.数组创建后, 如果没有赋值, 有默认的值
4.使用数组的步骤: (1)声明数组并开辟空间; (2)给数组各个元素赋值; (3)使用数组
5.数组的下标是从0开始的
6.数组下标必须在指定范围内使用, 否则报: 下标越界异常. 比如
int[] arr = new int[5]; 则有效下标为 0-4
即数组的下标/索引 最小 0 最大 数组长度-1(4)
7.数组属于引用类型, 数组型数据是对象(object)
public class ArrayDetail {
//编写一个main方法
public static void main(String[] args) {
//1.数组是多个相同类型数据的组合, 实现对这些数据的统一管理
// int[] arr1 = {1, 2, 3, 60, "hello"};//String -> int
double[] arr2 = {1.1, 2.2, 3.3, 60.6, 100};//int -> double
//2.数组中的元素可以是任意类型数据, 包括基本类型和引用类型, 但是不能混用
String[] arr3 = {"北京", "天安门", "tom"};
//3.数组创建后, 如果没有赋值, 有默认的值
// byte 0, short 0, int 0, long 0
// float 0.0, double 0.0
// char '\u0000', boolean false
// String null
short[] arr4 = new short[3];
System.out.println("===数组arr4===");
for(int i = 0; i < arr4.length; i++) {
System.out.println(arr4[i]);
}
//4.使用数组的步骤: (1)声明数组并开辟空间; (2)给数组各个元素赋值
//(3)使用数组
//5.数组的下标是从0开始的
//6.数组下标必须在指定范围内使用, 否则报: 下标越界异常. 比如
// int[] arr = new int[5]; 则有效下标为 0-4
// 即数组的下标/索引 最小 0 最大 数组长度-1 (4)
int arr5 = new int[5];
// System.out.println(arr5[5]);//数组越界
//7.数组属于引用类型, 数组型数据是对象(object)
}
}
1.创建一个char类型的26个元素的数组, 分别 放置 ‘A’ - ‘Z’. 使用for循环访问所有元素并打印出来. 提示: char类型数据运算 ‘A’ + 1 -> ‘B’ ArrayExercise01.java
public class ArrayExercise01 {
//编写一个main方法
public static void main(String[] args) {
/*
创建一个char类型的26个元素的数组, 分别 放置 'A' - 'Z'.
使用for循环访问所有元素并打印出来. 提示: char类型数据运算 'A' + 1 -> 'B'
思路分析
1.定义一个 char数组 char[] chars = new char[26];
2.因为 'A' + 1 = 'B'. 类推, 所以我们可以使用for循环来赋值
3.使用for循环访问所有元素
*/
char[] chars = new char[26];
for(int i = 0; i < chars.length; i++) {//循环26次
//chars 是 char[]
//chars[i] 是 char
chars[i] = (char)('A' + i);// 'A' + i 是 int, 需要强制转换
}
//循环输出
System.out.println("===chars数组===");
for(int i = 0; i < chars.length; i++) {
System.out.print(chars[i] + " ");
}
}
}
2.请求出一个数组int[]的最大值 {4, -1, 9, 10, 23}, 并得到对应的下标. ArrayExercise02.java
public class ArrayExercise02 {
//编写一个main方法
public static void main(String[] args) {
/*
请求出一个数组int[]的最大值 {4, -1, 9, 10, 23}, 并得到对应的下标.
思路分析
1. 定义一个int数组, int[] arr = {4, -1, 9, 10, 23};
2. 假定 max = arr[0] 是最大值, maxIndex = 0
3. 从下标 1 开始遍历arr, 如果max < 当前元素, 说明max
不是真正的最大值, 我们就 max = 当前元素; maxIndex=当前元素下标
4. 当我们遍历整个数组后, max就是真正的最大值, maxIndex就是最大值
对应的下标
*/
//代码实现
int[] arr = {4, -1, 9, 10, 23};
int max = arr[0];//假定第一个元素就是最大值
int maxIndex = 0;
for (int i = 1; i < arr.length; i++) {//从下标 1 开始遍历arr
if (max < arr[i]) {//如果max < 当前元素
max = arr[i];//把max 设置成当前元素
maxIndex = i;
}
}
//当我们遍历整个数组后, max就是真正的最大值, maxIndex就是最大值
System.out.println("max=" + max + " maxIndex=" + maxIndex);
}
}
1.基本类型赋值, 这个值就是具体的数据, 而且相互不影响
int n1 = 2; int n2 = n1;
2.组在默认情况下是引用传递, 赋的值是地址, 赋值方式为引用赋值
3.看一个案例 ArrayAssign.java
public class ArrayAssign {
//编写一个main方法
public static void main(String[] args) {
//基本数据类型赋值, 赋值方式为值拷贝
//n2的变化不会影响到n1的值
int n1 = 10;
int n2 = n1;
n2 = 80;
System.out.println("n1=" + n1);//10
System.out.println("n2=" + n2);//80
//数组在默认情况下是引用传递, 赋的值是地址, 赋值方式为引用赋值
//是一个地址, arr2的变化会影响到 arr1
int[] arr1 = {1,2,3};
int[] arr2 = arr1;//把 arr1赋给 arr2
arr2[0] = 10;
//看看arr1的值
System.out.println("===arr1的元素===");
for (int i = 0; i < arr1.length ; i++) {
System.out.println(arr1[i]);
}
System.out.println("===arr2的元素===");
for (int i = 0; i < arr2.length ; i++) {
System.out.println(arr2[i]);
}
}
}
编写代码, 实现数组拷贝(内容复制):
将 int[] arr1 = {10, 20, 30}; 拷贝到 arr2数组, 要求数据空间是独立的 ArrayCopy.java
public class ArrayCopy {
//编写一个main方法
public static void main(String[] args) {
//将 int[] arr1 = {10, 20, 30}; 拷贝到 arr2数组, 要求数据空间是独立的
int[] arr1 = {10, 20, 30};
//1.先创建一个新的数组arr2, 开辟新的数据空间[有新的数据空间, 就会有地址]
// 大小 arr1.length
int[] arr2 = new int[arr1.length];
//循环拷贝. 遍历 arr1, 把每个元素拷贝到arr2对应的元素位置
for(int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
//修改arr2, 不会对arr1有影响
arr2[0] = 100;
//输出arr1
System.out.println("===arr1的元素===");
for (int i = 0; i < arr1.length ; i++) {
System.out.println(arr1[i]);//10,20,30
}
System.out.println("===arr2的元素===");
for (int i = 0; i < arr2.length ; i++) {
System.out.println(arr2[i]);
}
}
}
要求: 把数组的元素内容反转. ArrayReverse.java
arr: {11, 22, 33, 44, 55, 66} ⇒ {66, 55, 44, 33, 22, 11}
●通过找规律反转
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}
//4. 一共要交换 3 次 = arr.length / 2
//5. 每次交换时, 对应的下标 是 arr[i] 和 arr[arr.length - 1 - i]
//优化
int len = arr.length;//计算数组的长度
int temp = 0;
//代码实现
for(int i = 0; i < len / 2; i++) {
temp = arr[len - 1 - i];//保存到临时变量
arr[len - 1 - i] = arr[i];
arr[i] = temp;
}
System.out.println("===反转后的数组===");
for(int i = 0; i < len; i++) {
System.out.print(arr[i] + " ");
}
}
}
数组反转内存分析图
public class ArrayReverse02 {
//编写一个main方法
public static void main(String[] args) {
//定义数组
int[] arr = {11, 22, 33, 44, 55, 66};
//使用逆序赋值方式
//思路分析
//1.先创建一个新的数组 arr2, 大小 arr.length
//2.逆序遍历 arr, 将每个元素拷贝到 arr2 元素中(顺序拷贝)
//3.建议增加一个循环变量 j -> 0 -> 5
int[] arr2 = new int[arr.length];
for (int i=arr.length - 1, j = 0; i >= 0; i--, j++) {
arr2[j] = arr[i];
}
//4.当for循环结束后, arr2就是一个逆序的数组 {66, 55, 44, 33, 22, 11};
//5.让 arr 指向 arr2数据空间, 此时 arr原来的数据空间就没有变量引用
// 会被当作垃圾, 销毁
arr = arr2;
//6.输出 arr 看看
System.out.println("===arr的元素情况===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
要求: 实现动态地给数组添加元素效果, 实现对数组扩容.ArrayAdd.java
1)原始数组使用静态分配 int[] arr = {1, 2, 3}
2)增加的元素4, 直接放在数组的最后 arr = {1, 2, 3, 4}
3)用户可以通过如下方法来决定是否继续添加, 添加成功, 是否继续? y/n
import java.util.Scanner;
public class ArrayAdd {
//编写一个main方法
public static void main(String[] args) {
/*
要求: 实现动态地给数组添加元素效果, 实现对数组扩容.
1)原始数组使用静态分配 int[] arr = {1, 2, 3}
2)增加的元素4, 直接放在数组的最后 arr = {1, 2, 3, 4}
3)用户可以通过如下方法来决定是否继续添加, 添加成功, 是否继续? y/n
思路分析
1.定义初始数组 int[] arr = {1, 2, 3};//下标0-2
2.定义一个新的数组 int[] newArr = new int[arr.length + 1];
3.遍历 arr 数组, 依次将arr地元素拷贝到 newArr 数组
4.将 4 赋值给 newArr. newArr[newArr.length - 1] = 4; 把4赋给newArr的最后一个元素
5.让 arr 指向 newArr. arr = newArr; 那么 原来的arr数组就被销毁
6.创建Scanner对象, 接收用户输入
7.定义一个变量 char answer, 用来决定是否继续
*/
//代码实现
//原始数组
int[] arr = {1, 2, 3};
//定义新数组引用
int[] newArr;
char answer = ' ';
Scanner myScanner = new Scanner(System.in);
do {
newArr = new int[arr.length + 1];
//数组拷贝
for(int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
newArr[newArr.length - 1] = 4;
arr = newArr;
//输出 arr
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.print("添加成功, 是否继续? y/n: ");
answer = myScanner.next().charAt(0);
}while(answer == 'y');
}
}
加上do-while循环
import java.util.Scanner;
public class ArrayAdd02 {
//编写一个main方法
public static void main(String[] args) {
/*
要求: 实现动态地给数组添加元素效果, 实现对数组扩容.
1)原始数组使用静态分配 int[] arr = {1, 2, 3}
2)增加的元素4, 直接放在数组的最后 arr = {1, 2, 3, 4}
3)用户可以通过如下方法来决定是否继续添加, 添加成功, 是否继续? y/n
思路分析
1.定义初始数组 int[] arr = {1, 2, 3};//下标0-2
2.定义一个新的数组 int[] arrNew = new int[arr.length + 1];
3.遍历 arr 数组, 依次将arr地元素拷贝到 arrNew 数组
4.将 4 赋值给 arrNew. arrNew[arrNew.length - 1] = 4; 把4赋给arrNew的最后一个元素
5.让 arr 指向 arrNew. arr = arrNew; 那么 原来的arr数组就被销毁
6.创建Scanner对象, 接收用户输入
7.因为用户什么时候退出, 不确定 我们使用 do-while+break 来控制
*/
//代码实现
Scanner myScanner = new Scanner(System.in);
//原始数组
int[] arr = {1,2,3};
do {
int[] arrNew = new int[arr.length + 1];
//遍历 arr 数组, 依次将arr的元素拷贝到 arrNew数组
for(int i = 0; i < arr.length; i++) {
arrNew[i] = arr[i];
}
System.out.print("请输入你要添加的元素: ");
int addNum = myScanner.nextInt();
//把4赋给arrNew最后一个元素
arrNew[arrNew.length - 1] = addNum;
//让 arr 指向 arrNew
arr = arrNew;
//输出arr 看看效果
System.out.println("===arr扩容后元素情况===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//问用户是否继续
System.out.print("\n是否继续添加 y/n: ");
char answer = myScanner.next().charAt(0);
if (answer != 'y') {//如果输入的不是y, 就结束
break;
}
} while(true);
System.out.println("你退出了添加...");
}
}
课后练习题: ArrayReduce.java
有一个数组 {1, 2, 3, 4, 5}, 可以将该数组进行缩减, 提示用户是否继续缩减, 每次缩减最后那个元素, 当只剩下最后一个元素, 提示, 不能再缩减
import java.util.Scanner;
public class ArraySub {
//编写一个main方法
public static void main(String[] args) {
/*
有一个数组 {1, 2, 3, 4, 5}, 可以将该数组进行缩减, 提示用户是否继续缩减,
每次缩减最后那个元素, 当只剩下最后一个元素, 提示, 不能再缩减
思路分析
1.定义初始数组 int[] arr = {1, 2, 3, 4, 5};//下标0-4
2.定义一个新数组 int[] newArr = new int[arr.length - 1];
3.遍历 arr 数组, 依次将arr的元素拷贝到 newArr 数组
4.让 arr 指向 newArr. arr = newArr; 那么 原来的arr数组就会被销毁
*/
//代码实现
int[] arr = {1, 2, 3, 4, 5};
int[] newArr = new int[arr.length - 1];
//遍历arr数组, 依次将arr的元素拷贝到 newArr数组
for(int i = 0; i < newArr.length; i++) {
newArr[i] = arr[i];
}
//让 arr指向newArr
arr = newArr;
//输出 arr
System.out.println("===arr缩减后元素情况===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
加上 do-while
import java.util.Scanner;
public class ArraySub02 {
//编写一个main方法
public static void main(String[] args) {
/*
有一个数组 {1, 2, 3, 4, 5}, 可以将该数组进行缩减, 提示用户是否继续缩减,
每次缩减最后那个元素, 当只剩下最后一个元素, 提示, 不能再缩减
思路分析
1.定义初始数组 int[] arr = {1, 2, 3, 4, 5};//下标0-4
2.定义一个新数组 int[] newArr = new int[arr.length - 1];
3.遍历 arr 数组, 依次将arr的元素拷贝到 newArr 数组
4.让 arr 指向 newArr. arr = newArr; 那么 原来的arr数组就会被销毁
5.创建Scanner对象, 接收用户输入
6.因为用户什么时候退出, 不确定. 我们使用 do-while 来控制
7.当只剩下最后一个元素, 提示, 不能再缩减
*/
//代码实现
Scanner myScanner = new Scanner(System.in);
int[] arr = {1, 2, 3, 4, 5};
do {
if (arr.length == 1) {
System.out.println("只剩下最后一个元素, 不能再缩减");
break;
}
int[] newArr = new int[arr.length - 1];
//遍历arr数组, 依次将arr的元素拷贝到 newArr数组
for(int i = 0; i < newArr.length; i++) {
newArr[i] = arr[i];
}
//让 arr指向newArr
arr = newArr;
//输出 arr
System.out.println("===arr缩减后元素情况===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//问用户是否继续
System.out.print("\n是否继续缩减 y/n: ");
char answer = myScanner.next().charAt(0);
if (answer != 'y') {//如果输入的不是y, 就结束
break;
}
}while(true);
}
}
排序是将多个数据, 依指定的顺序进行排列的过程
排序的分类:
1.内部排序
指将需要处理的所有数据都加载到内部存储器中进行排序. 包括(交换式排序法, 选择式排序法和插入式排序法)
2.外部排序法
数据量过大, 无法全部加载到内存中, 需要借助外部存储进行排序. 包括(合并排序法和直接合并排序法).
冒泡排序 (Bubble Sorting) 的基本思想是: 通过对待排序序列从后向前 (从下标较大的元素开始), 依次比较相邻元素的值, 若发现逆序则交换, 使值较大的元素逐渐从前移向后部, 就像水底下的气泡一样逐渐向上冒
●冒泡排序法案例
BubbleSort.java
下面我们举一个具体的案例来说明冒泡法. 我们将五个无序: 24, 69, 80, 57, 13, 使用冒泡排序法将其排成一个从小到大的有序数列
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]
*/
int[] arr = {24, 69, 80, 57, 13};
int temp = 0;//用于辅助交换的变量
for(int j = 0; j < 4; j++) {//比较4次
//如果前面的数大于后面的数, 就交换
if (arr[j] > arr[j+1]) {
//类似于推箱子
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;// [400, 10]
}
}
System.out.println("===第一轮===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
/*
第2轮排序: 目标把第二大数放在倒数第二位置
第1次比较[24,69,57,13,80]
第2次比较[24,57,69,13,80]
第3次比较[24,57,13,69,80]
*/
for(int j = 0; j < 3; j++) {//比较3次
//如果前面的数大于后面的数, 就交换
if (arr[j] > arr[j+1]) {
//类似于推箱子
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;// [400, 10]
}
}
System.out.println("\n===第2轮===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
/*
第3轮排序: 目标把第3大数放在倒数第3位置
第1次比较[24,57,13,69,80]
第2次比较[24,13,57,69,80]
*/
for(int j = 0; j < 2; j++) {//比较2次
//如果前面的数大于后面的数, 就交换
if (arr[j] > arr[j+1]) {
//类似于推箱子
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;// [400, 10]
}
}
System.out.println("\n===第3轮===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
/*
第4轮排序: 目标把第4大数放在倒数第4位置
第1次比较[13,24,57,69,80]
*/
for(int j = 0; j < 1; j++) {//比较1次
//如果前面的数大于后面的数, 就交换
if (arr[j] > arr[j+1]) {
//类似于推箱子
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;// [400, 10]
}
}
System.out.println("\n===第4轮===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
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]
*/
int[] arr = {24, 69, 80, 57, 13};
int temp = 0;//用于辅助交换的变量
//将多轮排序使用外层循环包括起来即可
for(int i = 0; i < 4; i++) {//外层循环是4次
for(int j = 0; j < 4 - i; j++) {//比较4次, 3次->2次-1次
//如果前面的数大于后面的数, 就交换
if (arr[j] > arr[j+1]) {
//类似于推箱子
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;// [400, 10]
}
}
System.out.println("\n===第" + (i+1) + "轮===");
for(int k = 0; k < arr.length; k++) {
System.out.print(arr[k] + "\t");
}
}
}
}
先死后活
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]
*/
int[] arr = {24, 69, 80, 57, 13, 99, 98, 97, -3};
int temp = 0;//用于辅助交换的变量
//将多轮排序使用外层循环包括起来即可
//先死后活 => 4就是 arr.length - 1
for(int i = 0; i < arr.length - 1; i++) {//外层循环是4次
for(int j = 0; j < arr.length - 1 - i; j++) {//比较4次, 3次->2次-1次
//如果前面的数大于后面的数, 就交换
if (arr[j] > arr[j+1]) {
//类似于推箱子
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;// [400, 10]
}
}
System.out.println("\n===第" + (i+1) + "轮===");
for(int k = 0; k < arr.length; k++) {
System.out.print(arr[k] + "\t");
}
}
}
}
●介绍
在java中, 我们常用的查找有两种:
SeqSearch.java
●案例演示
1.有一个数列: 白眉鹰王, 金毛狮王, 紫衫龙王, 青翼蝠王参数游戏: 从键盘中任意输入一个名称, 判断数列中是否包含此名称[顺序查找]. 要求: 如果找到了, 就提示找到, 并给出下标值.
import java.util.Scanner;
public class SequenceSearch {
//编写一个main方法
public static void main(String[] args) {
/*
有一个数列: 白眉鹰王, 金毛狮王, 紫衫龙王, 青翼蝠王参数游戏:
从键盘中任意输入一个名称, 判断数列中是否包含此名称[顺序查找].
要求: 如果找到了, 就提示找到, 并给出下标值.
思路分析
1.定义一个字符串数组 String[] players, 包含: {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"}
2.创建Scanner对象, 接收用户输入
3.定义一个变量 String findName, 保存名称
4.遍历数组, 逐一比较, 如果有, 则提供信息, 并输出
5.这里给大家介绍一个编程思想技巧, 一个经典的方法
*/
//代码实现
String[] players = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"};
System.out.print("请输入名字: ");
Scanner myScanner = new Scanner(System.in);
String findName = myScanner.next();
//遍历字符串数组, 逐一比较
//展示编程思想
int index= -1;
for(int i = 0 ; i < players.length; i++) {
//字符串 比较equals. 如果要找的名字就是当前元素
if (findName.equals(players[i])) {
System.out.print("找到啦 -> " + players[i]);
System.out.print(" 下标为 " + i);
//把i保存到index
index = i;
break;//退出
}
}
if (index == -1) {//没有找到
System.out.print("sorry, 没有找到 " + findName);
}
}
}
2.请对一个有序数组进行二分查找 {1, 8, 10, 89, 1000, 1234}, 输入一个数看看该数组是否存在次数, 并且求出下标, 如果没有就提示 “没有这个数”.
多维数组这里我们只学习二维数组
●二维数组的应用场景
比如我们开发一个五子棋游戏, 棋盘就是需要二维数组来表示.
●快速入门
TwoDimensionalArray01.java
请用二维数组输出如下图形
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0
public class TwoDimensionalArray01 {
//编写一个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
*/
//什么是二维数组
//解读
//1.从形式上看 int[][]
//2.可以这样理解 原来的一维数组的每个元素是一维数组, 就构成二维数组
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}};
//关于二维数组的关键概念
//(1)
System.out.println("二维数组的元素个数=" + arr.length);
//(2)二维数组的每个元素是一维数组, 所以如果需要得到每个一维数组的值,
// 还需要再次遍历
//(3)如果我们要访问第(i+1)个一维数组的第(j+1)个值 arr[i][j];
// 举例 访问 3 => 它是第3个一维数组的第4个值 a[2][3]
System.out.println("第3个一维数组的第4个值=" + arr[2][3]);
//输出二维图形
for(int i = 0; i < arr.length; i++) {//遍历二维数组的每个元素
//遍历二维数组的每个元素[数组]
//解读
//1.arr[i].length 得到 对应的 二维数组的每个一维数组的长度
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");//输出了一维数组
}
System.out.println();//换行
}
}
}
●使用方式一: 动态初始化
TwoDimensionalArray02.java
1.语法: 类型[][] 数组名 = new 类型[大小][大小]
2.比如: int a[][] = new int[2][3]
3.使用演示
public class TwoDimensionalArray02 {
//编写一个main方法
public static void main(String[] args) {
int arr[][] = new int[2][3];
arr[1][1] = 8;
//遍历arr数组
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("");
}
}
}
●使用方式2: 动态初始化 TwoDimensionalArray02.java
1.先声明: 类型 数组名[][];
2.再定义(开辟空间) 数组名= new 类型[大小][大小]
3.赋值(有默认值, 比如int 类型的就是0)
4.使用演示
public class TwoDimensionalArray02 {
//编写一个main方法
public static void main(String[] args) {
// int arr[][] = new int[5][21];
int arr[][];//先声明二维数组
arr = new int[2][3];//再开辟空间
arr[1][1] = 8;
//遍历arr数组
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("");
}
}
}
●使用方式3: 动态初始化-列数不确定 TwoDimensionalArray03.java
2.使用演示
public class TwoDimensionalArray03 {
//编写一个main方法
public static void main(String[] args) {
/*
看一个需求: 动态创建下面二维数组, 并输出
i = 1
i = 2 2
i = 3 3 3
一共有三个一维数组, 每个一维数组的元素是不一样的
*/
//创建 二维数组, 一共有3个一维数组, 但是每个一维数组还没有开空间
int[][] arr = new int[3][];
for(int i = 0; i < arr.length; i++) {// 遍历arr的每个一维数组
//给每个一维数组开辟空间 new
//如果没有给一维数组 new, 那么 arr[i]就是null
arr[i] = new int[i+1];
//遍历一维数组, 并给一维数组的每个元素赋值
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = i + 1;
}
}
//遍历arr输出
System.out.println("===arr的元素===");
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.定义: 类型 数组名[][] = {{值1, 值2…}, {值1, 值2…}, {值1, 值2…}};
2.使用即可 [固定方式访问]
比如: int[][] arr = {{1, 1, 1}, {4, 4, 3}, {100}};
解读 TwoDimensionalArray04.java
1.定义了一个二维数组 arr
2.arr有三个元素(每个元素都是一维数组)
3.第一个一维数组有3个元素, 第二个一维数组有3个元素, 第三个一维数组有1个元素
public class TwoDimensionalArray04 {
//编写一个main方法
public static void main(String[] args) {
//int无法转换为int[]
int[][] arr = {{1, 1, 1}, {4, 4, 3}, 100};
}
}
●案例
TwoDimensionalArray05.java
public class TwoDimensionalArray05 {
//编写一个main方法
public static void main(String[] args) {
/*
int arr[][] = {{4, 6}, {1, 4, 7, 5}, {-2}};
遍历该二维数组, 并得到和
思路分析
1.遍历该二维数组, 并将各个值累积到 int sum
*/
//代码实现
int arr[][] = {{4, 6}, {1, 4, 7, 5}, {-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);
}
}
● 杨辉三角
使用二维数组打印一个 10 行杨辉三角 YangHui.java
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
…
提示
1.每一行有1个元素, 第n行有n个元素
2.每一行的第一个元素和最后一个元素都是1
3.从第三行开始, 对于非第一个元素和最后一个元素的元素的值, arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
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.每一行有1个元素, 第n行有n个元素
2.每一行的第一个元素和最后一个元素都是1
3.从第三行开始, 对于非第一个元素和最后一个元素的元素的值
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];
//给每个一维数组(行) 赋值
for (int j = 0; j < yangHui[i].length; j++) {
//每一行有1个元素, 第n行有n个元素
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] + "\t");
}
System.out.println("");
}
}
}
1.一维数组的声明方式有: int[] x 或者int x[]
2.二维数组的声明方式有:
int[][] y 或者 int[] y[] 或者 int y[][]
3.二维数组的本质实际上是由多个一维数组组成的, 它的各个一维数组的长度可以相同, 也可以不相同.
比如: int map[][] 是一个二维数组. int map[][] = {{1, 2}, {3, 4, 5}};
4.由于 map[0] 是一个含有两个元素的一维数组, map[1] 是一个含有三个元素的一维数组构成, 我们也称map为列数不等的二维数组.
●二维数组课堂练习
声明:
int[] x,y[]; 以下选项允许通过编译的是(b, e).
说明: x是int类型的一维数组, y是int类型的二维数组
a) x[0] = y; //错误 int[][] -> int
b) y[0] = x; //正确
c) y[0][0] = x; //错误 int[] -> int
d) x[0][0] = y; //错误 x[0][0],写法错误
e) y[0][0] = x[0]; //正确 int -> int
f) x = y; //错误 int[][] -> int[]
1.下面的数组定义正确的有(B D). Homework01.java
A. String strs[] = {‘a’, ‘b’, ‘c’}; //错误 char -> String
B. String[] strs = {“a”, “b”, “c”}; //正确
C. String[] strs = new String{“a”, “b”, “c”}; //error
D. String strs[] = new String[]{“a”, “b”, “c”}; //正确
E. String[] strs = new String[3]{“a”, “b”, “c”}; //error, 编译不通过
2.试写出结果. Homework02.java
String foo = “blue”;
boolean[] bar = new boolean[2]; //bar[0] 默认 false
if(bar[0]) {
foo = “green”;
}
System.out.println(foo); //blue
3.以下Java代码的输出结果为 (1 3 5 7). Homework03.java
int num = 1;
while(num < 10) {
System.out.println(num);
if(num > 5) {
break;
}
num += 2;
}
4.已知有个升序的数组, 要求插入一个元素, 该数组顺序依次是升序, 比如 [10, 12, 45, 90], 添加23 后, 数组为 [10, 12, 23 ,45, 90]. Homework04.java
public class Homework04 {
//编写一个main方法
public static void main(String[] args) {
//代码实现
//先定义原数组
int[] arr = {10, 12, 45, 90};
int insertNum = 23;
int index = -1;//index就是要插入的位置
//遍历 arr数组, 如果发现 insertNum<=arr[i], 说明 i 就是要插入的位置
//使用 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;
}
//扩容
//先创建一个新的数组, 大小 arr.length + 1
int[] arrNew = new int[arr.length + 1];
//下面准备将arr的元素拷贝到 arrNew, 并且跳过 index位置
/*
分析
int[] arr = {10, 12, 45, 90};
arrNew = { }
*/
//i用来控制arrNew数组的下标, j用来控制arr数组的下标
for(int i = 0, j = 0; i < arrNew.length; i++) {
if (i != index) {//说明可以把 arr的元素拷贝到 arrNew
arrNew[i] = arr[j];
j++;
} else {//i这个位置就是要插入的数
arrNew[i] = insertNum;
}
}
//让arr 指向 arrNew, 原来的数组, 就成为 垃圾, 被销毁
arr = arrNew;
System.out.println("===插入后arr数组的元素情况===");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
5.随即生成10个整数(1-100的范围)保存到数组. 并倒序打印以及求平均值, 求最大值和最小值的下标, 并查找里面是否有8. Homework05.java
random函数
public class Homework05 {
//编写一个main方法
public static void main(String[] args) {
/*
随即生成10个整数(1-100的范围)保存到数组. 并倒序打印以及求平均值,
求最大值和最小值的下标, 并查找里面是否有8.
思路分析
*/
// 1.定义一个数组, 大小 10, 并赋值
int[] arr = new int[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 100) + 1;
}
System.out.println("===arr的元素情况===");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//2. 倒序打印
System.out.println("\n===arr的元素情况(倒序打印)===");
for (int i = arr.length - 1; i >= 0; i--) {
System.out.print(arr[i] + "\t");
}
//3.求平均值
// 求最大值和最小值的下标
// 可以一起完成
double sum = arr[0];//累积求和
int max = arr[0];//保存最大值
int maxIndex = 0;//保存最大值下标
int min = arr[0];//保存最小值
int minIndex = 0;//保存最小值下标
//遍历arr
for (int i = 1; i < arr.length; i++) {
sum += arr[i];//累积求和
if (max < arr[i]) {//说明假定的max不是最大值, 就变化
max = arr[i];
maxIndex = i;
}
if (min > arr[i]) {//说明假定的min不是最小值, 就变化
min = arr[i];
minIndex = i;
}
}
System.out.println("\n最大值" + max + " 下标=" + maxIndex);
System.out.println("最小值" + min + " 下标=" + minIndex);
System.out.println("平均值=" + (sum / arr.length));
//4.查找数组中是否有 8 -> 使用顺序查找
/* int findNum = 8;
int index = -1;//如果找到, 就把下标记录到 index
for (int i = 0; i < arr.length; i++) {
if (findNum == arr[i]) {
index = i;
break;
}
}
if (index != -1) {
System.out.println("找到了" + findNum + " 下标=" + index);
} else {
System.out.println("没有发现8");
}*/
//5.查找数组中是否有 8 -> 使用顺序查找
// 分别输出 8 的下标
int[] arr2 = {8, 8, 8, 8, 8, 1, 8, 2, 8, 3, 8, 4, 5, 8, 8, 9, 8, 10};
int findNum = 8;
int[] index = new int[0];//如果找到, 就把index数组扩容, 然后把下标记录到 index
int[] indexNew = null;
for (int i = 0; i < arr2.length; i++) {
if (findNum == arr2[i]) {
indexNew = new int[index.length + 1];
for (int j = 0; j < index.length; j++) {
indexNew[j] = index[j];
}
indexNew[indexNew.length - 1] = i;
index = indexNew;
}
}
if (index.length > 0) {
for (int i = 0; i < index.length; i++) {
System.out.print(index[i] + "\t");
}
}
}
}
6.试写出以下代码的打印结果. Homework06.java
public class Homework06 {
//编写一个main方法
public static void main(String[] args) {
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
z z
赵 赵
c c
7.写出冒泡排序的代码 Homework07.java
public class Homework07 {
//编写一个main方法
public static void main(String[] args) {
/*
写出冒泡排序的代码
假如要对 int[] arr = {12, 4, 3, -12, -5}; 进行从小到大排序
运用冒泡排序
1.我们一共有5个元素
2.一共进行了4轮排序, 可以看成是外层循环 4 = 5-1
i -> 0 内层循环4次 j < 4 4 + i = 4 4 = 4 - i = 5 - 1 - i
i -> 1 内层循环3次 j < 3 3 + i = 4 3 = 4 - i = 5 - 1 - i
i -> 2 内层循环2次 j < 2 2 + i = 4 2 = 4 - i = 5 - 1 - i
i -> 3 内层循环1次 j < 1 1 + i = 4 1 = 4 - i = 5 - 1 - i
3.每轮排序都会确定一个数的位置.
比如第1轮排序确定最大的数最值
第2轮排序确定倒数第二大的数位置
第3轮排序确定倒数第三大的数位置
4.如果前面的数大于后面的数, 就交换
5.每轮比较在减少
*/
int[] arr = {12, 4, 3, -12, -5, 6, 9, 13, -14};
int temp = 0;//定义一个临时变量
for (int i = 0; i < arr.length - 1; i++) {//有5个元素, 外层循环排序4次
for (int j = 0; j < arr.length - 1 - i; j++) {//j=4次 -> 3次->2次->1次
//前面的数大于后面的数, 就交换
//如果是从大到小 条件是 arr[j] < arr[j+1]
//如果是从小到大 条件是 arr[j] > arr[j+1]
if (arr[j] > arr[j+1]) {
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
System.out.println("===输出arr===");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}