JAVA语言语法_数组(part4)

JAVA语言语法

四、数组
1、数组的概述
数组的概述:
(1)、数组的理解: 数组Array,是多个相同类型的数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
(2)、数组的相关概念:
	> 数组名
	> 元素
	> 角标、下标、索引
	> 数组的长度,元素的个数
(3)、数组的特点:
	1)、数组属于引用数据类型的变量,数组的元素,既可以是基本数据类型,也可以是引用数据类型。
	2)、创建数组对象会在内存中开辟一整块连续的空间。
	3)、数组的长度一旦确定,就不能修改了。
	4)、数组是有序排列的。
(4)、数组的分类:
	①.按照维数: 可划分为 一维数组、二维数组、三维数组。
	②.按照数组的元素类型: 可划分为 基本数据类型、引用类型元素的数组
2、一维数组的使用
数组讨论学习点:
(1)、数组的声明和初始化;
(2)、如何调用数组的指定位置的元素;
(3)、如何获取数组的长度;
(4)、如何遍历数组;
(5)、数组元素的默认值初始值;
(6)、数组的内存解析。

代码演示(针对上述的6个学习点):

package com.rucoding.d7;

/**
 * @author LiuYiXin
 *
 */
public class ArrayDemo01 {
	public static void main(String[] args) {

		/*
		 * (1)、数组的声明和初始化; 引用数据类型:数组的声明和初始化
		 */

		// 回顾基本数据类型的声明和初始化
		int i1; // 声明变量类型
		i1 = 10; // 初始化
		int i2 = 10; // 声明和初始化

		// 类比
		int[] arr; // 数组声明
		// 静态初始化: 数组的初始化和数组元素的赋值同时进行
		arr = new int[] { 1, 2, 3, 4 }; // 初始化: 静态初始化
		// 动态初始化: 数组的初始化和数组元素的赋值操作分开进行
		String[] names = new String[5];

		/*
		 * (2)、如何调用数组的指定位置的元素; 通过角标、下标、索引(一个意思)方式调用 数组的角标索引从0开始,到数组的长度 - 1结束的
		 */
		// names数组元素进行赋值操作
		names[0] = "张三";
		names[1] = "李四";
		names[2] = "王五";
		names[3] = "赵六";
		names[4] = "田七";
		// names[5] = "老八";//如果数组超过角标会通过编译,但是运行的时候会失败。java.lang.ArrayIndexOutOfBoundsException

		/*
		 * (3)、如何获取数组的长度;
		 */
		//属性,不是方法,length属性
		System.out.println(arr.length); //4
		System.out.println(names.length); //5
		
		
		/*
		 * (4)、如何遍历数组;
		 */
		//遍历数组元素,循环输出即可
		for(int i = 0;i < names.length;i++){
			System.out.println(names[i]);
		}
		
		
		/*
		 * (5)、数组元素的默认值初始值;
		 * 总结:
		 * 1)、数组整型的默认初始化值为0
		 * 2)、浮点型的默认初始化值为0.0
		 * 3)、布尔类型的默认初始化值为false
		 * 4)、char字符类型的默认初始化值为0,而非'0'
		 * 5)、引用数据类型数组(比如String类型)的默认初始化值为null
		 */
		
		//数组的默认初始化值
		int[] arrInt = new int[4];
		for(int i = 0;i < arrInt.length;i++){
			System.out.println(arrInt[i]); //整型默认初始化的值为0
		}
		
		short[] arrShort = new short[4];
		for(int i = 0;i < arrShort.length;i++){
			System.out.println(arrShort[i]);//整型默认初始化的值为0
		}
		
		//浮点型
		float[] arrFloat = new float[4];
		for(int i = 0;i < arrFloat.length;i++){
			System.out.println(arrFloat[i]);//浮点型默认初始化的值为0.0
		}
		
		//布尔类型
		boolean[] arrBoolean = new boolean[4];
		for(int i = 0;i < arrBoolean.length;i++){
			System.out.println(arrBoolean[i]);//布尔类型默认初始化的值为false
		}
		
		//char类型
		char[] arrChar = new char[4];
		for(int i = 0;i < arrChar.length;i++){
			System.out.println(arrChar[i]);//char类型默认初始化的值为0,而非'0'
		}
		//验证
		if(arrChar[0] == 0){
			System.out.println("Hi");
		}
		
		//String类型
		String[] arrString = new String[4];
		for(int i = 0;i < arrString.length;i++){
			System.out.println(arrString[i]);//String类型(引用数据类型)默认初始化的值为null
		}
		
		//Verify
		if(arrString[0] == null){
			System.out.println("Rucoding");
		}
		
	}
}

第(6)个学习点:

(6)、数组的内存解析。

内存的简化结构:

在这里插入图片描述

2.1 一维数组的内存解析
分析以下代码的内存结构图:

int[] arr = new int[]{1,2,3}; //静态声明一个int类型的arr数组,并赋值1,2,3 三个元素
String[] arr1 = new String[4]; //动态声明一个引用类型的arr1数组,并初始化长度为4
arr1[1] = “刘德华”;  //给动态声明长度为4的arr数组,赋值操作
arr1[2] = “张学友”; //给动态声明长度为4的arr数组,赋值操作
arr1 = new String[3]; //重新创建一个开辟连续空间的,初始化长度为3的数组给arr1
System.out.println(arr1[1]);//null //此时打印输出的,引用类型默认的初始化值为null

内存解析图(大概意思):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UrF6WYyU-1634137509963)(C:\Users\哎小彬\AppData\Roaming\Typora\typora-user-images\image-20211011150542122.png)]

按照图示内容,最终数组的内存解析完成,数组内部值为null。

3、数组练习

​ 练习1:通过数组来打印个人的手机号码(调皮一下)。

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class ArrayPrintTelDemo01 {
	//通过数组来打印个人的手机号码 13620167671(随机生成的,请勿拨打!)
	public static void main(String[] args) {
		//定义一个数组,并静态赋值手机号出现的数字
		int[] telNum = new int[]{7,3,6,2,0,6,1};
		//手机号码是11位的,遍历11次,取上面telNum数组对应的索引值, 组成手机号码
		int[] arr1 = {6,1,2,3,4,6,5,0,5,0,6};
		//定义我的号码变量
		String myTel = "";	
		for(int i = 0;i < arr1.length;i++){
			myTel += telNum[arr1[i]];
		}
		System.out.print("我的联系方式:" + myTel);
		
	}
}	

来源于:

/*
 * 升景坊单间短期出租4个月,550元/月(水电煤公摊,网费35元/月),空调、卫生间、厨房齐全。
 * 屋内均是IT行业人士,喜欢安静。所以要求来租者最好是同行或者刚毕业的年轻人,爱干净、安静。
 * eclipse代码一键格式规范化:Ctrl+Shift+F
 */
public class ArrayDemo {
	public static void main(String[] args) {
		int[] arr = new int[] { 8, 2, 1, 0, 3 };
		int[] index = new int[] { 2, 0, 3, 2, 4, 0, 1, 3, 2, 3, 3 };
		String tel = "";
		for (int i = 0; i < index.length; i++) {
			tel += arr[index[i]];
		}
		System.out.println("联系方式:" + tel);
	}
}

​ 练习2:

	/*
	 * 2. 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
	 * 成绩>=最高分-10    等级为’A’   
	 * 成绩>=最高分-20    等级为’B’
	 * 成绩>=最高分-30    等级为’C’   
	 * 其余等级为’D’
	 * 提示:先读入学生人数,根据人数创建int数组,存放学生成绩。
	 */

代码演示:

package com.rucoding.d7.exer;

import java.util.Scanner;

/**
 * @author LiuYiXin
 *
 */
public class ArrayStuScoreDemo02 {
	/*
	 * 2. 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
	 * 成绩>=最高分-10    等级为’A’   
	 * 成绩>=最高分-20    等级为’B’
	 * 成绩>=最高分-30    等级为’C’  
	 * 其余等级为’D’
	 * 提示:先读入学生人数,根据人数创建int数组,存放学生成绩。
	 */
	
	public static void main(String[] args) {
		
		//声明一个可以接收键盘输入的Scanner类
		Scanner scanner = new Scanner(System.in);
		//此时可以创建数组, 动态初始化
		System.out.println("请输入学生人数:");
		int num = scanner.nextInt();
		int[] stuNum = new int[num];
		//定义一个最高分的变量
		int maxScore = 0;
		
		//录入学生成绩
		System.out.println("请输入" + stuNum.length + "个成绩:");
		for(int i = 0;i < stuNum.length;i++){
			stuNum[i] = scanner.nextInt();
			//录入的成绩的同时,比较录入的最高分
			if(maxScore < stuNum[i]){
				maxScore = stuNum[i]; 
			}
		}
		
		//打印最高分
		System.out.println("最高分是:" + maxScore);
		
		//定义一个等级的变量
		char level;
		
		//遍历学生成绩,并判断登记
		for(int i = 0;i < stuNum.length;i++){
			if(maxScore - stuNum[i] <= 10){ //
				level = 'A';
			}else if(maxScore - stuNum[i] <= 20){
				level = 'B';
			}else if(maxScore - stuNum[i] <= 30){
				level = 'C';
			}else{
				level = 'D';
			}
			System.out.println("student " + i + " score is " + stuNum[i] + " grade is " + level);
		}
			
	}
	
}

4、二维数组的定义和遍历

​ 二维数组从底层的运行机制来看也是一维数组,以一维数组的6个讨论要点来分析二维数组。

二维数组的使用:
格式1(动态初始化): int[][] arr = new int[3][2];
定义了一个名称为arr的二维数组
二维数组中有3个一维数组
每个一维数组中有2个元素
一维数组的名称分别为,arr[0]、arr[1]、arr[2]
假如给一个一维数组1下标赋值66的写法,arr[0][1] = 66。

格式2(动态初始化): int[][] arr = new int[3][];
二维数组中有3个一维数组。
每个一维数组都是默认的初始化值null (注意区别于格式1)
可以对这个三个一维数组分别进行初始化。
arr[0] = new int[3];
arr[1] = new int[1];
arr[2] = new int[2];

代码演示:

package com.rucoding.d7;

/**
 * @author LiuYiXin
 *
 */
public class ArrayDemo02 {
	/*
	 * 二维数组的使用
	 * ①.理解
	 * 对于二维数组的理解, 可以看成是一维数组arr1又作为另一个一维数组arr2的元素
	 * 其实,从数组底层的运行机制来看,没有多维数组的概念
	 * 
	 * ②.
	 * a.二维数组的声明和初始化
	 * b.获取数组指定位置的元素
	 * c.获取数组的长度
	 * d.遍历数组
	 * e.数组元素的默认初始值
	 * f.数组的内存解析
	 */
	public static void main(String[] args) {
		//a.二维数组的声明和初始化
		//静态初始化
		int[][] arr = new int[][]{{1,2,3},{2,3,4},{5,6},{7,8}};
//		int[][] arr = {{1,2,3},{2,3,4},{5,6}}; 这种写法也可以的
		//动态初始化1
		int[][] arr1 = new int[3][2];
		//动态初始化2
		int[][] arr2 = new int[3][];
		
		
		//这里与 “e.数组元素的默认初始值” 讨论大体相同,跳过忽略也可。
		System.out.println(arr[2][1]); //打印数组arr的6
		System.out.println(arr1[0][0]); //打印数组arr1中的arr[0]一维数组中的0索引元素
		System.out.println(arr2[0]); //每个一维数组都是默认的初始化值null (数组是引用类型,默认为null)
		arr2[0] = new int[3];
		arr2[1] = new int[1];
		arr2[2] = new int[2];
		System.out.println(arr2[0][0]); //此时默认为一维数组的元素已经进行初始化,int类型默认为0
		System.out.println(arr2[0]); //arr2[0] 此时是一个地址值[I@15db9742 [表示一维数组,I表示int类型
		
		
		//b.如何调用指定位置的元素
		String[][] names = new String[3][2];
		System.out.println(arr[2][0]); //打印5
		System.out.println(names[2][1]); //null
		
		//c.获取数组的长度
		System.out.println(names.length); //3
		System.out.println(names[0].length); //2
		System.out.println(arr.length); //3
		
		System.out.println("**********************");
		
		//d.遍历数组
		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("**********************");
		//e.数组元素的默认初始值 (重点理解)
		/*
		 * 二维数组的使用:
		 * 规定:二维数组分为外层数组的元素,内层数组的元素
		 * int[][] arr = new int[4][3];
		 * 	外层元素: arr[0]、arr[1]、arr[2]、arr[3]
		 * 	内层元素: arr[0][0]、arr[0][1]、arr[0][2]等
		 * 
		 * 数组元素的默认初始化值
		 * 针对于初始化方式一:比如:int[][] arr = new int[4][3];
		 * 	外层元素的初始化值为:地址值
		 * 	内层元素的初始化值为:与一维数组初始化情况相同
		 * 针对于初始化方式而:比如:int[][] arr = new int[4][];
		 * 	外层元素的初始化值为:null
		 * 	内层元素的初始化值为:不能调用,否则报错。
		 */
		int[][] arrInt = new int[4][3];
		System.out.println(arrInt[0]); //[I@6d06d69c 地址值
		System.out.println(arrInt[0][0]); //0
		
		float[][] arrFloat = new float[4][3];
		System.out.println(arrFloat[0]); //[F@7852e922 地址值
		System.out.println(arrFloat[0][0]); //0.0
		
		short[][] arrShort = new short[4][3];
		System.out.println(arrShort[0]); //[S@4e25154f 地址值
		System.out.println(arrShort[0][0]); //0
		
		System.out.println("**********************");
		char[][] arrChar = new char[4][3];
		System.out.println(arrChar[0]); // 地址值 
		System.out.println(arrChar[0][0]); //
		
		String[][] arrString = new String[4][3];
		System.out.println(arrString[0]); //[Ljava.lang.String;@70dea4e 地址值
		System.out.println(arrString[0][0]); //null

		System.out.println("**********************");
		double[][] arrDouble = new double[4][3];
		System.out.println(arrDouble[0]); // [D@5c647e05 地址值 
		System.out.println(arrDouble[0][0]); //0.0
		
		arrDouble = new double[4][];
		System.out.println(arrDouble[0][0]);//报错 空指针异常NullPointerException
	}
}
4.1、二维数组的内存解析
①、分析以下代码的内存结构图:

int[][] arr1 = new int[4][];
arr1[1] = new int[]{1,2,3};
arr1[2] = new int[4];
arr1[2][1] = 30;

在这里插入图片描述

②、分析以下代码的内存结构图:

int[][] arr4= new int[3][];
System.out.println(arr4[0]);//null
System.out.println(arr4[0][0]);//报错
arr4[0] = new int[3];
arr4[0][1] = 5;
arr4[1] = new int[]{1,2};

在这里插入图片描述

③、分析以下代码的内存结构图:

int[][] arr = new int[3][];
arr[1] = new int[]{1,2,3};
arr[2] = new int[3];
System.out.println(arr[0]);//null
System.out.println(arr[0][0]);//报异常

在这里插入图片描述

④、分析以下代码的内存结构图:

int[][] arr1= newint[4][];
arr1[0] = new int[3];
arr1[1] = new int[]{1,2,3};
arr1[0][2] = 5;
arr1 = new int[2][];

在这里插入图片描述

4.2、二维数组的练习

​ 练习1:

在这里插入图片描述

代码演示:

package com.rucoding.d7;

/**
 * @author LiuYiXin
 *
 */
public class ArraySumDemo03 {
	public static void main(String[] args) {
		//按照图示求和
		int sum = 0;
		int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
		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);
	}
}

练习2:

int[] x 这是一个一维数组,int[] y[] 这是一个二维数组,即int[][] y

tips: 同一类型或者自下而上的转型。

在这里插入图片描述

练习3:

/* 使用二维数组打印一个 10 行杨辉三角。
 *
 * 【提示】
 * 1. 第一行有 1 个元素, 第 n 行有 n 个元素
 * 2. 每一行的第一个元素和最后一个元素都是 1
 * 3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。
 * 即:yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
 */

在这里插入图片描述

先输出整体的框架,创建一个长度为10的二维数组 new int[10][],默认每个位置的初始化值都是0 ,此时再一一进行赋值,先确定赋值的是:每行的首尾都是1。

填充好每行首尾的1,其他位置再根据提示的公式,进行赋值即可。

示例代码:

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class YangHuiArrayDemo01 {
//	使用二维数组打印一个 10 行杨辉三角。
	public static void main(String[] args) {
		//确定了数组长度
		int[][] arr = new int[10][];
		for(int i = 0;i < arr.length;i++){
			//初始化一维数组长度
			arr[i] = new int[i + 1];
			//首尾元素赋值
			arr[i][0] = 1;
			arr[i][i] = 1;
			
			//给非首尾元素赋值
			for(int j = 1;j < i;j++){//循环条件 j < arr[i].length-1; 
				arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
			}
			
		}
		
		//遍历输出数组
		for(int i = 0;i < arr.length;i++){
			for(int j = 0;j < arr[i].length;j++){
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println();
		}
		
	}
}

练习4(面试题目):

创建一个长度为 6 的 int 型数组,要求取值为 1-30,同时元素值各不相同。

代码演示:

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class ArrayRandomDemo04 {
	public static void main(String[] args) {
		/*创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值。
		* 同时,要求元素的值各不相同。
		*
		*/
		//定义长度为6的数组
		int[] arr = new int[6];
		for(int i = 0;i < arr.length;i++){
			arr[i] = (int) ((Math.random()*30) + 1);
			System.out.println(arr[i]);
			//判断每次随机生成的数 在数组中是否重复
			for(int j = 0;j < i;j++){
				if(arr[i] == arr[j]){
//					i = i - 1; //此时是重复的,不让继续下一个,继续执行当前i的赋值
					i--; //换种写法
//					continue lable;
					break;
				}	
			}		
		}
		
		//遍历
		for(int i = 0;i < arr.length;i++){
			System.out.print(arr[i] + "\t");
		}
		System.out.println();
		
			
	}
}
5、数组中涉及到的常见算法
(1)、数组元素的赋值(杨辉三角、回形数等)
(2)、求数值型数组中元素的最大值、最小值、平均数、总和等
(3)、数组的复制、反转、查找(线性查找、二分法查找)
(4)、数组元素的排序算法
5.1、数组元素的赋值

​ 查看上述练习3<杨辉三角的打印>

5.2、数组元素的基本操作

代码演示:

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class ArrayBasicOperationDemo01 {
	/*
	 * 算法的考察:求数值型数组中元素的最大值、最小值、平均数、总和等
	 * 
	 * 定义一个 int 型的一维数组,包含 10 个元素,分别赋一些随机整数,
	 * 然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。
	 * 要求:所有随机数都是两位数。
	 * 
	 * [10,99]
	 * 公式:(int)(Math.random() * (99 - 10 + 1) + 10)
	 */

	public static void main(String[] args) {
		
		//定义长度为10的数组
		int[] arr = new int[10];
		//定义变量
		int maxNum = 0;
		int minNum = 0;
		int sum = 0;
		double aveNum = 0.0;
		
		int len = arr.length;
		
		
		//数组进行赋值
		for(int i = 0;i < arr.length;i++){
			//输出10到99之间的随机数
			arr[i] = (int) (Math.random()*(99 - 10 + 1) + 10);
		}
		
		
		//求最大值
		for(int i = 0;i < arr.length;i++){
			if(maxNum < arr[i]){
				maxNum = arr[i];
			}
		}
		
		//求最小值
		minNum = arr[0];
		for(int i = 0;i < arr.length;i++){
			if(minNum > arr[i]){
				minNum = arr[i];
			}
		}
		
		//求总和
		for(int i = 0;i < arr.length;i++){
			sum += arr[i];
		}
		
		//求平均值
		aveNum = sum / len;
		
		//遍历数组
		for(int i = 0;i < arr.length;i++){
			if(i != arr.length -1){
				System.out.print(arr[i] + ",");
			}else{
				System.out.print(arr[i]);
			}
			
		}
		
		System.out.println();
		System.out.println("最大值" + maxNum);
		System.out.println("最小值" + minNum);
		System.out.println("总和" + sum);
		System.out.println("平均值" + aveNum);
		
	}	
}
5.3、数组元素的基本操作 2

代码演示:

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class ArrayBasicOperationDemo02 {
	/*
	 * 使用简单数组
	 * (1)创建一个名为 ArrayTest 的类,在 main()方法中声明 array1 和 array2 两个变量,他们是 int[]类型的数组。
	 * (2)使用大括号{},把 array1 初始化为 8 个素数:2,3,5,7,11,13,17,19。
	 * (3)显示 array1 的内容。
	 * (4)赋值 array2 变量等于 array1,修改 array2 中的偶索引元素,使其等于索引值(如 array[0]=0,array[2]=2)。打印出 array1。
	 */

	public static void main(String[] args) {
		int[] array1,array2;
		array1 = new int[]{2,3,5,7,11,13,17,19};
		
		//显示 array1 的内容
		for(int i = 0;i < array1.length;i++){
			System.out.print(array1[i] + "\t");
		}
		
		//赋值 array2 变量等于 array1
		array2 = array1;  //此处是数组的赋值,不是复制!
		
		//修改 array2 中的偶索引元素,使其等于索引值(如 array[0]=0,array[2]=2)
		for(int i = 0;i < array2.length;i++){
			if(i % 2 == 0){
				array2[i] = i;
			}
		}
		
		System.out.println();
		
		//打印出 array1。
		for(int i = 0;i < array1.length;i++){
			System.out.print(array1[i] + "\t");
		}
		
	}
	
}

针对此题,停下来思考一下:

思考1:上述 array1 和 array2 是什么关系?
//array1 和 array2 地址值相同,都指向了堆空间的唯一的一个数组实体。
int[] array1,array2;
array1 = new int[]{2,3,5,7,11,13,17,19};
array2 = array1; //赋值 ,实际还是指向堆空间同一地址值
for(int i = 0;i < array2.length;i++){
	if(i % 2 == 0){
		array2[i] = i;
	}
}

内存结构分析图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3T3DGiu-1634137509967)(C:\Users\哎小彬\AppData\Roaming\Typora\typora-user-images\image-20211013121823379.png)]

思考2: 如何实现 array2 对 array1 数组的复制
int[] array1,array2;
array1 = new int[]{2,3,5,7,11,13,17,19};
//数组的复制
array2 = new int[array1.length]; //new关键字是创建对象,开辟新空间
for(int i = 0;i < array2.length;i++){
	array2[i] = array1[i];
}

内存结构分析图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GpgzsUNn-1634137509968)(C:\Users\哎小彬\AppData\Roaming\Typora\typora-user-images\image-20211013122457775.png)]

5.4、数组的复制、反转、查找

代码演示:

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class ArrayBasicOperationDemo04 {
	/*
	 * 算法的考察:数组的复制、反转、查找(线性查找、二分法查找)
	 */
	public static void main(String[] args) {
		//数组的复制
		String[] arr = new String[]{"CC","FF","SS","QQ","YY","XX","TT","KK","EE","GG"};
		String[] arr1 = new String[arr.length];
		for(int i = 0;i< arr1.length;i++){
			arr1[i] = arr[i];
		}
		
		//遍历
		for(int i = 0;i< arr1.length;i++){
			System.out.print(arr1[i] + "\t");
		}
		
		System.out.println();
		
		//数组的反转  考虑首尾对调
//		int index = 0;
//		int endIndex = arr1.length -1;
//		while(index < endIndex){
//			//交换两个数,之前写过的, 定义一个临时变量
//			String temp = arr1[index];
//			arr1[index] = arr1[endIndex];
//			arr1[endIndex] = temp;
//			index++;
//			endIndex--;
//		}
		//优化写法
		for(int i = 0,j = arr1.length - 1;i < j;i++,j--){
			String temp = arr1[i];
			arr1[i] = arr[j];
			arr[j] = temp;
		}
		
		//遍历输出
		for(int i = 0;i< arr1.length;i++){
			System.out.print(arr1[i] + "\t");
		}
		
		System.out.println();
		
		//查找(即是搜索) 
		//线性查找
		boolean isFlag = true;
		String target = "HH";
		for(int i = 0 ;i < arr1.length;i++){
			if(target.equals(arr1[i])){ //字符串是利用equals()方法
				isFlag = false;
				System.out.println("找到了");
				break;
			}
		}
		if(isFlag){
			System.out.println("很遗憾,没找到对应的");
		}	
		
 	}
}

查找之二分法查找(折半查找)

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IpkBwTz0-1634137509968)(C:\Users\哎小彬\AppData\Roaming\Typora\typora-user-images\image-20211013153725558.png)]

代码演示:

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class ArrayBasicOperationDemo04 {
	/*
	 * 算法的考察:数组的复制、反转、查找(线性查找、二分法查找)
	 */
	public static void main(String[] args) {
		//二分法查找(折半查找) : 前提是所要查找的数组是有序的
		int[] arr2 = new int[]{-8,-314,22,24,53,66,79,105,98,123};
		int targetNum = 12;
		int headIndex = 0; //初始的首所索引
		int endIndex = arr2.length - 1;  //初始的末索引
		boolean isFlag2 = true;
		while(headIndex <= endIndex){
			int middleIndex = (headIndex + endIndex) / 2;		
			if(targetNum == arr2[middleIndex]){
				System.out.println("找到了");
				isFlag2 = false;
				break;
			}else if(targetNum > arr2[middleIndex]){
				headIndex = middleIndex + 1; 
			}else{
				endIndex = middleIndex - 1;
			}		
		}
		
		if(isFlag2){
			System.out.println("很遗憾,没找到对应的");
		}
		
 	}
}
5.5、数组元素的排序算法
(1)、排序:假设含有 n 个记录的序列为{R1,R2,…,Rn},其相应的关键字序列为{K1,K2,…,Kn}。将这些记录重新排序为{Ri1,Ri2,…,Rin},使得相应的关键字值满足条 Ki1<=Ki2<=…<=Kin,这样的一种操作称为排序。
通常来说,排序的目的是快速查找。
(2)、衡量排序算法的优劣:
	时间复杂度:分析关键字的比较次数和记录的移动次数
	空间复杂度:分析排序算法中需要多少辅助内存
	稳定性:若两个记录 A 和 B 的关键字值相等,但排序后 A、B 的先后次序保持不变,则称这种排序算法是稳定的。
(3)、排序算法分类:内部排序和外部排序。
	内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
	外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。
	外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。

5.5.1、十大内部排序算法

(1)、选择排序
	直接选择排序、堆排序
(2)、交换排序
	冒泡排序(重点掌握)、快速排序(暂时了解即可)
(3)、插入排序
	直接插入排序、折半插入排序、Shell 排序
(4)、归并排序
(5)、桶式排序
(6)、基数排序

温馨提示: 以上算法,重点掌握手写冒泡排序,快速排序暂时了解, 其他有兴趣有时间再去研究。

5.5.2、算法的 5 大特征

在这里插入图片描述

5.5.3、冒泡排序(重要)

冒泡排序的基本思想:
通过对待排序序列从前向后,依次比较相邻元素的排序码,若发现逆序则交换,使排序码较大的元素逐渐从前部移向后部。
因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序, 因此要在排序过程中设置一个标志swap判断元素是否进行过交换。从而减少不必要的比较。

图解示范

在这里插入图片描述

代码演示(要求会手写):

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class BubbleArrayDemo {
	public static void main(String[] args) {
		//经典排序: 冒泡排序
		int[] arr = new int[]{12,-34,4,18,40,-2,0,78}; //len 8
		//
		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]){
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
		
		for(int i = 0;i < arr.length;i++){
			System.out.print(arr[i] + "\t");
		}
		
	}
}

5.5.4、快速排序(初学Java,仅作了解)

排序思想:

从数列中挑出一个元素,称为"基准"(pivot),
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

图解示范:
在这里插入图片描述

5.5.5、排序算法性能对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p6ZC3mR3-1634137509971)(C:\Users\哎小彬\AppData\Roaming\Typora\typora-user-images\image-20211013164146483.png)]

各种内部排序方法性能比较:

(1)、从平均时间而言:快速排序最佳。但在最坏情况下时间性能不如堆排序和归并排序。
(2)、从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是简单算法。对于Shell排序、堆排序、
	 快速排序和归并排序算法,其算法比较复杂,认为是复杂排序。
(3)、从稳定性看:直接插入排序、冒泡排序和归并排序是稳定的;而直接选择排序、快速排序、Shell排序和堆排序是不稳定排序
(4)、从待排序的记录数n的大小看,n较小时,宜采用简单排序;而n较大时宜采用改进排序。

排序算法的选择:
(1)、 若n较小(如n≤50),可采用直接插入或直接选择排序。当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接	  插入,应选直接选择排序为宜。
(2)、 若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序为宜;
(3)、 若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。
6、Arrays 工具类的使用
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
boolean equals(int[] a,int[] b)判断两个数组是否相等
String toString(int[] a)输出数组信息
void fill(int[] a,int val)将指定值填充到数组之中
void sort(int[] a)对数组进行排序
int binarySearch(int[] a,int key)对排序后的数组进行二分法检索指定的值

代码演示:

package com.rucoding.d7.exer;

import java.util.Arrays;

/**
 * @author LiuYiXin
 *
 */
public class ArraysUtilDemo {
	public static void main(String[] args) {
		//1.boolean equals(int[] a,int[] b) 判断两个数组是否相等
		int[] arr1 = new int[]{1,2,3,4};
		int[] arr2 = new int[]{1,2,4,3};
		boolean isEquals = Arrays.equals(arr1, arr2);
		System.out.println(isEquals);
		
		//2.String toString(int[] a) 输出数组元素信息
		System.out.println(Arrays.toString(arr1)); //[1, 2, 3, 4]
		System.out.println(Arrays.toString(arr2)); //[1, 2, 4, 3]
		
		
		//3.void fill(int[] a,int val) 将指定值填充到数组之中
		Arrays.fill(arr1, 2);
		System.out.println(Arrays.toString(arr1)); //[2, 2, 2, 2]
		
		//4.void sort(int[] a) 对数组进行排序
		Arrays.sort(arr2);
		System.out.println(Arrays.toString(arr2)); //[1, 2, 3, 4]
		
		//5.int binarySearch(int[] a,int key) 对排序后的数组进行二分法检索指定的值。
		int[] arr = new int[]{12,-34,4,18,40,-2,0,78};
		Arrays.sort(arr);
		System.out.println(Arrays.toString(arr)); //默认升序
		int index = Arrays.binarySearch(arr, 24);
		if(index >= 0){ //看底层key找不到的情况下,是返回负数的
			System.out.println(index);
		}else{
			System.out.println("很遗憾, 没有找到! " + index);
		}
		
	}
}
7、数组使用中的常见异常
数组中的常见异常:
(1)、数组角标越界的异常:ArrayIndexOutOfBoundsException
(2)、空指针异常:NullPointerException

代码演示:

package com.rucoding.d7.exer;

/**
 * @author LiuYiXin
 *
 */
public class ArrayExceptionDemo {
	/*
	 * 数组中的常见异常:
	 * 1.数组角标越界的异常:ArrayIndexOutOfBoundsException
	 * 
	 * 2.空指针异常:NullPointerException
	 * 
	 */
	public static void main(String[] args) {
		//1.数组角标越界的异常:ArrayIndexOutOfBoundsException
		int[] arr = new int[]{1,2,3,4};
		//错误场景1
		for(int i = 0;i <= arr.length;i++){
//			System.out.println(arr[i]); //java.lang.ArrayIndexOutOfBoundsException
		}
		
		//错误场景2
//		System.out.println(arr[-2]);

		//2.空指针异常:NullPointerException
		int[] arr1 = new int[]{1,2,3,4};
		arr1 = null;
		//错误场景1
//		System.out.println(arr1[0]); //java.lang.NullPointerException
		//错误场景2
		int[][] arr2 = new int[4][];
//		System.out.println(arr2[0][0]);
		//错误场景3
		String[] arr3 = new String[]{"AA","QQ","YY","XX","TT","KK"};
		arr3[0] = null;
		System.out.println(arr3[0].toString());
		
	}
}

本文到此结束,感谢浏览~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java智慧阁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值