Java零基础入门:数组深度探究和练习
在上一章中,我们学会了如何定义和遍历数组。但在实际开发中,对数据的处理远不止“存”和“取”这么简单。如何在一万条成绩中找到最高分?如何把杂乱无章的订单金额从小到大排列?如何快速在电话簿中找到一个名字?
本章将带你走进数组的核心操作。我们将手把手实现求最大最小值、三大经典排序算法(冒泡、选择、插入)、高效的二分查找,并解锁Java官方自带的Arrays工具类。掌握它们,你的Java逻辑思维将迈上一个全新的台阶!
1.数组中的最大值最小值
我们可以想象一场比武大会,当第一位选手上台的时候,会作为暂时擂主,第二位选手上台的时候就需要和第一位选手进行比赛,胜出者作为擂主,后面的选手依次上台进行对擂主的挑战,直到所有人比完,最后的擂主就是胜出者
Public class MaxMinDemo{
Public static void main(String[] args){
Int max=scores[0];int min scores[0];
For(int i=1;i<scores.length;i++{
If(scores[i]>max){
Max=scores[i];}
If(scores[i]<min){
Min=scores[i];}}
System.out.println("本次比武的最高分是:" + max);
System.out.println("本次比武的最低分是:" + min);}}
2.冒泡排序算法(Bubble Sort)
冒泡排序是算法界中的“hello world”,效率虽然不是最高的,但它能极好的训练你的循环和逻辑思维能力。简单的来说,它就是重复的走访要排序的数列,依次比较相邻的两个元素,如果顺序错误(前面比后面大),就交换它们,每一轮比较后,最大的元素就会像泡泡一样,”浮”到数组的末尾。
其过程类似于以 {5, 3, 8, 4, 2} 为例),第1轮:3,5,4,2,[8] (8冒到最后),第2轮:3,4,2,[5, 8] (5冒到倒数第二),第3轮:3,2,[4, 5, 8],第4轮:2,[3, 4, 5, 8]
Public class BubbleSortDemo{
Public static void main(String[] args){
Int[] arr={5,3,8,4,2};
For(int i=0;i<arr.length;i++){
For(int j;j<arr.length-1-I;j++){
If(arr[j]>arr[j+1]){
Int temp = arr[j];
Arr[j]=arr[j+1];
Arr[j+1]=temp;}}
System.out.println("第" + (i + 1) + "轮排序后:" + java.util.Arrays.toString(arr));}}}
记住口诀:外层管轮数,内层管比较;两两相比大就换,外层减一内减外。
3.选择排序法(Selection Sort)
冒泡排序是“频繁交换”,而选择排序更像是“选秀”:先在所有的选手中挑出最帅的(最小值),让他站到第一个位置。然后在剩下的选手中再挑最帅的,站到第二个位置。以此类推。
public class SelectionSortDemo {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 4, 2};
for (int i = 0; i < arr.length - 1; i++) { // 外层循环:控制选择的轮数
int minIndex = i; // 假设当前位置就是最小值的位置
for (int j = i + 1; j < arr.length; j++) { // 内层循环:从 i+1 开始,寻找真正的最小值的索引
if (arr[j] < arr[minIndex]) {
minIndex = j; // 记录更小值的索引}}
if (minIndex != i) { // 如果最小值不在当前位置,就交换一次
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;} }
System.out.println("选择排序结果:" + java.util.Arrays.toString(arr));} }
与冒泡的区别:冒泡排序每一轮可能交换很多次,而选择排序每一轮只交换一次,性能稍好。
4.直接插入排序算法(Insertion Sort)
这是最符合人类直觉的排序方法。左手拿着已经排好序的牌(初始只有第一张)。右手摸到一张新牌,从右向左依次比较,找到合适的位置插入。
public class InsertionSortDemo {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 4, 2};
for (int i = 1; i < arr.length; i++) { // 从第二张牌开始摸(索引1)
int current = arr[i]; // 右手摸到的当前牌
int j = i - 1; // 左手已有牌的最后一张
while (j >= 0 && arr[j] > current) { // 在左手的牌中从右向左扫描,如果牌比current大,就往后挪一位
arr[j + 1] = arr[j]; // 元素后移
j--;}
arr[j + 1] = current;} // 找到位置,插入当前牌
System.out.println("插入排序结果:" + java.util.Arrays.toString(arr));} }
对于基本有序的数据,插入排序的效率非常高。
5. 二分查找算法(Binary Search)
数组必须是有序的!(通常是从小到大)。如果数组无序,请先使用 Arrays.sort() 排序。让你在 1-100 之间猜一个数字,你肯定先猜 50。如果猜大了,说明目标在 1-49 之间;
如果猜小了,说明目标在 51-100 之间。每次排除一半的数据,这就是二分查找,效率极高!
public class BinarySearchDemo {
public static void main(String[] args) {
int[] arr = {2, 3, 4, 5, 8, 10, 15}; // 必须是有序数组
int target = 5; // 要找的目标
int left = 0;
int right = arr.length - 1;
int result = -1; // 找不到返回-1
while (left <= right) {
int mid = (left + right) / 2; // 找到中间索引
if (arr[mid] == target) {
result = mid; // 找到了!
break;
} else if (arr[mid] > target) {
right = mid - 1; // 目标在左半边,缩小右边界
} else {
left = mid + 1; // 目标在右半边,缩小左边界}}
if (result != -1) {
System.out.println("恭喜,找到元素 " + target + ",索引位置是:" + result);
} else {
System.out.println("抱歉,数组中不存在元素 " + target);}}}
100个元素,顺序查找最多找100次;二分查找最多只需要 7次(log₂100)。
6. Arrays 工具类(开发必备神器)
Java 官方提供了一个超级好用的工具类 java.util.Arrays,里面封装了现成的方法,让我们不用重复造轮子。
方法 | 功能说明 |
Arrays.toString(arr) | 将数组转换成漂亮的字符串,方便打印 |
Arrays.sort(arr) | 对数组进行升序排序(底层是优化后的快速排序) |
Arrays.binarySearch(arr, key) | 对已排序数组进行二分查找,返回索引(找不到返回负数) |
Arrays.fill(arr, value) | 用指定值填满整个数组 |
Arrays.copyOf(arr, length) | 复制数组 |
import java.util.Arrays; // 注意:必须导入这个包
public class ArraysToolDemo {
public static void main(String[] args) {
int[] numbers = {9, 1, 5, 3, 7};
Arrays.sort(numbers); // 1. 排序
System.out.println("排序后:" + Arrays.toString(numbers));
int index = Arrays.binarySearch(numbers, 5); // 2. 二分查找(必须在排序后使用!)
System.out.println("元素5的索引是:" + index);
int[] placeholder = new int[3]; // 3. 填充数组
Arrays.fill(placeholder, 100);
System.out.println("填充后:" + Arrays.toString(placeholder));
int[] newArr = Arrays.copyOf(numbers, numbers.length); // 4. 复制数组
System.out.println("复制的新数组:" + Arrays.toString(newArr));}}
ArrayIndexOutOfBoundsException(数组索引越界)
数组的索引是从 0 到 length-1。千万不要写 arr[arr.length],这会直接报错!
二分查找前忘了排序,如果数组 {3, 1, 4} 没排序就直接用 binarySearch 找 4,结果是不可预知的。
排序算法的选择,作为初学者,理解冒泡、选择、插入的原理是为了锻炼思维。但在实际开发中,请直接使用 Arrays.sort(),它经过高度优化,效率远高于我们手写的简单排序。
每日练习:
定义一个 double 类型的数组 {89.5, 92.0, 76.5, 88.0},计算班级平均分。
修改冒泡排序的代码,让它变成从大到小排序。
创建一个字符串数组 {"banana", "apple", "pear", "orange"},使用 Arrays.sort() 排序,并遍历输出。
编写一个方法 public static int search(int[] arr, int target),用顺序查找(不用二分)实现查找目标元素,返回索引。
会做的小伙伴也可将答案发在评论区中,我们一起探讨!