自己的笔记记录,Java的基础知识(第四期)(本期笔记的内容有:一维数组、二维数组)

继续记录Java的基础知识,方便自己查看,各位要是有需要也可以copy一下。
本期笔记的内容有:一维数组、二维数组

一维数组的内存的一些解析:
以五行代码为例:

int[] arr = new int[]{1,2,3};
String[] arr1 = new String[4];
arr1[1] = "刘德华";
arr1[2] = "张学友";
arr1 = new String[3];

创建了一个名为arr的int类型的一维数组和一个名为arr1的String类型的一维数组,并给arr数组中的三项分别赋值1、2、3,给arr1数组的第二项赋值 “刘德华” 、第三项赋值 “张学友”。变量名arr和arr1都存放在栈中,而这些通过new创建的数据则存放在堆中,堆根据代码的命令(例如数组arr)创建一个相对应的数组(数组中每一项的值都为初始值),这个被创建出来的数组会有一个首地址值(通常用一个十六进制的数表示,图中假设首地址值为:0x34ab),这个首地址值会赋值给存放在栈中的变量名arr,由此变量名arr便可通过赋值的首地址值,准确找到存放在堆中的所对应的数组,并给这个数组赋值1、2、3。
如下图:
一维数组内存解析
一维数组内存解析
数组arr1同理,如下图:
一维数组内存解析
一维数组内存解析
以上四句代码执行完后,看到第五句代码“arr1 = new String[3]”,给变量名arr1再赋值一个新的长度为三的String类型的数组,该数组的首地址值为:0x5566,此时,变量名arr1所指向的数组发生了变化,变量名arr1中的值则从原先的0x12ab变成了0x5566,由于变量名arr1赋值的地址值发生了变化,变量名arr1不再指向原先的数组,指向了新创建的首地址值为0x5566的数组。
一维数组内存解析
一维数组内存解析

二维数组的内存的一些解析:
规定:二维数组分为外层数组元素、内层数组元素。
int[][] arr = new int[4][3];
外层元素:arr[0]、arr[1]、arr[2]…
内层元素:arr[0][0]、arr[0][1]、arr[0][2]…

以四行代码为例:

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

第一行代码“int[][] arr1 = new int[4][];”,堆根据代码的命令创建了一个名为arr1的int类型的一维数组,给arr数组中的外层元素赋值一个4。和一维数组一样,变量名arr1存放在栈中,而这些通过new创建的数据则存放在堆中,堆根据代码的指示创建一个拥有四个存储空间的一维数组(由于二维数组arr1数组的内层元素未声明空间,所以每一项的值都看作为一维数组int[],初始值为null),创建出来的这个一维数组会有一个首地址值(通常用一个十六进制的数表示,图中假设首地址值为:0x1234),这个首地址值会赋值给存放在栈中的变量名arr1,由此变量名arr1便可通过赋值的首地址值,准确找到存放在堆中的所对应的数组。
如下图:
二维数组内存解析
第二行代码“arr1 = new int[]{1,2,3};”,堆根据代码的命令创建一个拥有三个存储空间的int类型的一维数组(每一项的值都看作为一维数组int[]的初始值0),创建出来的这个一维数组会有一个首地址值(通常用一个十六进制的数表示,图中假设首地址值为:0x7788),这个首地址值会赋值给第一行代码创建出来的一维数组的第二项中,由此第一行代码创建出来的一位数组的第二项的值便从原来的null变成了第二行代码所创建出来的一维数组的首地址值,并根据代码的指示,给这个一维数组的三个存储空间分别赋值1、2、3。
二维数组内存解析
第三行代码“arr1 = new int[4];”,堆根据代码的命令创建一个拥有四个存储空间的int类型的一维数组(由于第一行代码处,该二维数组是一个int类型的二维数组,所以每一项的值都看作为一维数组int[]的初始值0),创建出来的这个一维数组会有一个首地址值(通常用一个十六进制的数表示,图中假设首地址值为:0x6677),这个首地址值会赋值给第一行代码创建出来的一维数组的第三项中,由此第一行代码创建出来的一维数组的第三项的值便从原来的null变成了第三行代码所创建出来的一维数组的首地址值。
二维数组内存解析
第四行代码“arr1[2][1] = 30;”,堆根据代码的命令,找到二维数组arr1的第三个外层元素所指向的数组中的第二项,并将该项的值由原来的0更改为30。
二维数组内存解析

package lian_xi;

import java.util.Scanner; //导入输入函数

/*
 * 一、数组的概述
 * 1)数组的理解:数组(Array),是多个相同类型数据按照一定顺序排列的集合,并使用一个名字
 * 命名,并通过编号的方式对这些数据进行统一管理。
 * 
 * 2)数组相关的概念:
 * 	 ① 数组名
 * 	 ② 元素
 * 	 ③ 角标、下标(索引)
 * 	 ④ 数组的长度:元素的个数
 * 
 * 3)数组的特点:
 * 	 ① 数组是有序排列的(排列顺序自己定义)
 * 	 ② 数组本身是引用数据类型的变量,而数组中的元素可以是任何数据类型,包括基本数据类型和引
 * 	 用数据类型。
 * 	 ③ 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
 * 	 ④ 数组的长度一旦确定,就不能修改。
 * 	 ⑤ 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
 * 
 * 4)数组的分类:
 * 	 ① 按照维度:一维数组、二维数组、三维数组、...
 * 	 ② 按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)
 * 
 * 5)一维数组的使用:
 *   ① 一维数组的声明和初始化方式: type VAR[]; 或 type[] VAR;
 *   	总结:数组一旦初始化完成,其长度就确定了,不可改变。
 *   
 * 	 ② 如何调用数组指定位置的元素:数组名[数组元素下标]
 * 		总结:a.数组元素下标可以是整型常量或整型表达式。如 a[3],b[i],c[6*i];
 * 			  b.数组元素下标从 0 开始:长度为n的数组合法下标取值范围:0——>n-1 如int a[]=new int [3];
 *				可引用的数组元素为 a[0]、a[1]、a[2];
 *
 * 	 ③ 如何获取数组的长度: 属性 length
 * 		总结:a.length,指明数组a的长度(元素个数)
 * 
 * 	 ④ 如何遍历数组:直接输出或者使用for循环之类的循环结构
 * 
 * 	 ⑤ 数组元素的默认初始化值
 * 		总结:a.数组元素是整数型:0
 * 			  b.数组元素是浮点型:0.0
 *  		  c.数组元素是char型:ASCII码中的0 或 '\u0000' , 而非'0'
 *  		  d.数组元素是boolean型:false
 *  		  e.数组元素是引用数据类型:null(空值)
 *  
 *   ⑥ 数组的内存解析:
 *   	总结:a.栈(stack): 局部变量
 * 			  b.堆(heap): new出来的结构、对象、数组
 *  		  c.方法区: 常量池、静态池
 * 
 */

public class lianxi04 {
	public static void main(String[] args) {
		
		// ① 一维数组的声明和初始化方式: type VAR[]; 或 type[] VAR;
		
		//例如:
		int[] ids;  //声明
		//1.1静态初始化:数组的初始化和数组元素的赋值操作同时进行
		ids = new int[]{1001,1002,1003,1004};
		
		//1.2动态初始化:数组的初始化和数组元素的赋值操作分开进行
		String[] names = new String[5];
		int[] namess = {1,2,3,4,5,6};
		
		/* 错误的写法:
		 *   ① int[] arr1 = new int[];  未声明长度
		 *   ② int[5] arr2 = new int[5];  前方中括号内不能有值
		 *   ③ int[] arr3 = new int[5]{1,2,3};  动态初始化和静态初始化不能合并使用
		 *   
		 *   总结:数组一旦初始化完成,其长度就确定了,不可改变。
		 */
		
		// ② 如何调用数组指定位置的元素:数组名[数组元素下标]
		//数组元素下标从 0 开始:长度为n的数组合法下标取值范围:0——>n-1
		//例如:
		names[0] = "一";
		names[1] = "二";
		names[2] = "三";
		names[3] = "四";
		names[4] = "五";
		
		// ③ 如何获取数组的长度:每个数组都有一个属性 length 指明它的长度
		//例如: a.length 指明数组 a 的长度 元素个数
		System.out.println("数组ids的长度为:" + ids.length);  //数组ids的长度为4
		System.out.println("数组names的长度为:" + names.length);  //数组names的长度为5
		System.out.println("数组namess的长度为:" + namess.length);  //数组ids的长度为6
		
		// ④ 如何遍历数组: 直接输出或者使用for循环之类的循环结构
		//方法一:
		System.out.print(names[0]);
		System.out.print(names[1]);
		System.out.print(names[2]);
		System.out.print(names[3]);
		System.out.print(names[4]+'\n');
		//方法二:
		for( int i = 0 ; i < names.length ; i++ ) {
			System.out.print(names[i]);
		}System.out.println(); //换行
		
		// ⑤ 数组元素的默认初始化值: 
		int[] arr1 = new int[4];
		for( int i = 0 ; i < arr1.length ; i++ ) {
			System.out.print(arr1[i]);  //输出0
		}System.out.println(); //换行
		
		short[] arr2 = new short[4];
		for( int i = 0 ; i < arr2.length ; i++ ) {
			System.out.print(arr2[i]);  //输出0
		}System.out.println(); //换行
		
		char[] arr3 = new char[4];
		for( int i = 0 ; i < arr3.length ; i++ ) {
			System.out.print(arr3[i]);  //输出ASCII码中的0 或 '\u0000' , 而非'0'
		}System.out.println(); //换行
		
		boolean[] arr4 = new boolean[4];
		for( int i = 0 ; i < arr4.length ; i++ ) {
			System.out.print(arr4[i]);  //输出false
			System.out.print('\t');
		}System.out.println(); //换行
		
		String[] arr5 = new String[4];
		for( int i = 0 ; i < arr5.length ; i++ ) {
			System.out.print(arr5[i]);  //输出null(空值)
			System.out.print('\t');
		}System.out.println(); //换行
		
		
		/* 练习;
		 * 从键盘读入学生成绩,找出最高分,
		 * 并输出学生成绩等级。
		 * 成绩 >= 90 并且 成绩<= 100 等级为 ’A’
		 * 成绩 >= 80 并且 成绩< 90 等级为 ’B’
		 * 成绩 >= 70 并且 成绩< 80 等级为 ’C’
		 * 成绩 >= 60 并且 成绩< 70 等级为 ’D’
		 * 其余 等级 为 ‘E’
		 * 
		 * 提示:先读入学生人数,根据人数创建int数组,存放学生成绩、
		 */
		System.out.println("一维数组练习:");
		// 1)使用Scanner,读取学生个数。		
		Scanner scanner = new Scanner(System.in);  //Scanner的实例化
		
		System.out.print("请输入学生人数:");
		int number = scanner.nextInt();
		
		// 2)创建数组,存储学生成绩,动态初始化。
		int[] scores = new int[number];
		
		// 3) 给数组中的元素赋值。
		int maxScore = 0;  //用于记录最高分的分数
		int ranking = 0;  //用于记录最高分在第几位
		System.out.println("请输入" + number + "个学生成绩(成绩不大于100,不小于0):");
		for( int i = 0 ; i < scores.length ; i++ ) {
			scores[i] = scanner.nextInt();
			// 4) 在for循环中嵌套一个if判定来获取数组中的元素的最大值(即最高分)
			if ( maxScore < scores[i] ) {
				maxScore = scores[i];
				ranking = i+1;
			}			
		}
		//输出最高分
		System.out.println("其中成绩最高的是第"+ ranking +"位学生,其成绩为:"+ maxScore);
		
		// 5) 判断每个学生的等级,并输出成绩和等级
		for( int i = 0 ; i < scores.length ; i++ ) {
			if( scores[i] >= 90 && scores[i] <= 100 ) {
				System.out.println("第"+ (i+1) +"位学生的等级为:A 成绩:"+ scores[i]);
			}else if( scores[i] >= 80 && scores[i] < 90 ) {
				System.out.println("第"+ (i+1) +"位学生的等级为:B 成绩:"+ scores[i]);
			}else if( scores[i] >= 70 && scores[i] < 80 ) {
				System.out.println("第"+ (i+1) +"位学生的等级为:C 成绩:"+ scores[i]);
			}else if( scores[i] >= 60 && scores[i] < 70 ) {
				System.out.println("第"+ (i+1) +"位学生的等级为:D 成绩:"+ scores[i]);
			}else if( scores[i] >= 0 && scores[i] < 60 ) {
				System.out.println("第"+ (i+1) +"位学生的等级为:E 成绩:"+ scores[i]);
			}
		}
		
		
		/*
		 * 二维数组的使用:
		 * 规定:二维数组分为外层数组元素、内层数组元素。
		 * 		int[][] arr = new int[4][3];
		 * 		外层元素:arr[0]、arr[1]、arr[2]....
		 * 		内层元素:arr[0][0]、arr[0][1]、arr[0][2]....
		 * 
		 * 1)理解:对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维
		 * 数组 array2 的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。
		 * 
		 * 5)二维数组的使用:
		 *   ① 二维数组的声明和初始化方式: 
		 *   	格式一(静态初始化): int[][] arr = new int[][]{{1,2,3},{4,5},{6,7,8}};
		 *   	格式二(动态初始化):int[][] arr = new int[n][m]; 
		 *   	格式三(动态初始化):int[][] arr = new int[n][];
		 *   	格式四(动态初始化): int arr[][] = new int [n][m];
		 *   	格式五(动态初始化): int[] arr[] = new int [n][m];
		 *   	格式六(动态初始化): int[][] arr = {{1,2,3},{4,5},{6,7,8}}; 
		 *   	总结:数组一旦初始化完成,其长度就确定了,不可改变。
		 *   
		 * 	 ② 如何调用数组指定位置的元素:数组名[数组元素下标][数组元素下标]
		 * 		总结:a.数组元素下标可以是整型常量或整型表达式。如 a[3][2],b[i][n],c[6*i][n*i];
		 * 			  b.数组元素下标从 0 开始:长度为n的数组合法下标取值范围:0——>n-1 如int a[]=new int [3][2];
		 *				可引用的数组元素为 a[0][0]、 a[0][1]、a[1][0]、a[1][1]、a[2][0]、a[2][1];
		 *
		 * 	 ③ 如何获取数组的长度: 属性 length
		 * 		总结:arr.length,指明数组arr的外层的长度(元素个数)
		 * 			  arr[n].length,指明数组arr第n层的长度(元素个数)
		 * 
		 * 	 ④ 如何遍历数组:直接输出或者使用for循环之类的循环结构
		 * 
		 * 	 ⑤ 数组元素的默认初始化值
		 * 		总结:
		 * 		针对于初始化方式一: 如:int[][] arr = new int[n][m];
		 * 		  对于变量名本身来说:
		 * 			  数组的初始值为: 首地址值 
		 * 		  对于外层元素来说:
		 * 			  数组的初始值为: 首地址值
		 * 		  对于内层元素来说:
		 * 			  a.数组元素是整数型:0
		 * 			  b.数组元素是浮点型:0.0
		 *  		  c.数组元素是char型:ASCII码中的0 或 '\u0000' , 而非'0'
		 *  		  d.数组元素是boolean型:false
		 *  		  e.数组元素是引用数据类型:null(空值 )
		 *  
		 *  	针对于初始化方式二: 如:int[][] arr = new int[n][];
		 * 		  对于变量名本身来说:
		 * 			  数组的初始值为: 首地址值 
		 * 		  对于外层元素来说:
		 * 			  数组的初始值为: null
		 * 		  对于内层元素来说:
		 * 			  无初始化,报错,错误原因”空指针异常“
		 *  
		 *   ⑥ 数组的内存解析:
		 *   	总结:a.栈(stack): 局部变量
		 * 			  b.堆(heap): new出来的结构、对象、数组
		 *  		  c.方法区: 常量池、静态池 
		 */
		
		// ① 二维数组的声明和初始化方式:
		//格式一(静态初始化): int[][] arr = new int[][]{{1,2,3},{4,5},{6,7,8}};
		int[][] arr6 = new int[][]{{1,2,3},{4,5},{6,7,8}};
		// 格式二(动态初始化): int[][] arr = new int [n][m]; 
		String[][] arr7 = new String[3][2];
		// 格式三(动态初始化): int[][] arr = new int [n][]; 
		String[][] arr8 = new String[3][];
		// 格式四(动态初始化): int arr[][] = new int [n][m]; 
		String  arr9[][]  = new String[3][2];
		// 格式五(动态初始化): int[] arr[] = new int [n][m]; 
		String[]  arr10[]  = new String[3][2];
		// 格式六(动态初始化): int[][] arr = {{1,2,3},{4,5},{6,7,8}};
		int[][] arr11 = {{1,2,3},{4,5},{6,7,8}};
		
		/* 错误的写法:
		 *   ① String[][] arr = new String[][m];  
		 *   ② String[n][m] arr = new String[][];
		 *   ③ String[n][m] arr = new String[n][m];
		 *   
		 *   总结:数组一旦初始化完成,其长度就确定了,不可改变。
		 */
		
		// ② 如何调用数组指定位置的元素:数组名[数组元素下标][数组元素下标]
		System.out.println(arr6[0][1]);  //输出2
		System.out.println(arr7[0][1]);  //输出null(空值)
		System.out.println(arr9[0][1]);  //输出null(空值)
		System.out.println(arr10[0][1]);  //输出null(空值)
		System.out.println(arr11[0][1]);  //输出2
		//不能直接输出数组arr8,因为数组arr8的第二个维度还未赋值,若直接输出会出现“空指针异常”
		arr8[1] = new String[4];
		System.out.println(arr8[1][0]);  //输出null(空值)
		
		// ③ 如何获取数组的长度: 属性 length
		System.out.println("数组arr6的外层有"+ arr6.length +"个元素");  //输出3
		System.out.println("数组arr6第1层中有"+ arr6[0].length +"个元素");  //输出3
		
		// ④ 如何遍历数组:直接输出或者使用for循环之类的循环结构
		System.out.println("数组arr6里的各项如下:");  //输出3
		for ( int i = 0 ; i < arr6.length ; i++ ) {
			for (int j = 0 ; j < arr6[i].length ; j++) {
				System.out.print(arr6[i][j] + "\t");  //输出3				
			}
			System.out.println();  //换行
		}
		
		// ⑤ 数组元素的默认初始化值 
		int[][] arr12 = new int[4][3];
		System.out.println(arr12);  //输出 [[I@74a14482 (首地址值)
		System.out.println(arr12[0]);  //输出 [I@1540e19d (首地址值)
		System.out.println(arr12[0][0]);  //输出 0
		
		float[][] arr13 = new float[4][3];
		System.out.println(arr13);  //输出 [[F@677327b6 (首地址值)
		System.out.println(arr13[0]);  //输出 [F@14ae5a5 (首地址值)
		System.out.println(arr13[0][0]);  //输出 0.0
		
		char[][] arr14 = new char[4][3];
		System.out.println(arr14);  //输出 [[C@7f31245a (首地址值)
		System.out.println(arr14[0]);  //输出 ASCII码中的0 或 '\u0000' , 而非'0'
		System.out.println(arr14[0][0]);  //输出 ASCII码中的0 或 '\u0000' , 而非'0'
		
		boolean[][] arr15 = new boolean[4][3];
		System.out.println(arr15);  //输出 [[Z@6d6f6e28 (首地址值)
		System.out.println(arr15[0]);  //输出 [Z@135fbaa4 (首地址值)
		System.out.println(arr15[0][0]);  //输出 false
		
		String[][] arr16 = new String[4][3];
		System.out.println(arr16);  //输出 [[Ljava.lang.String;@45ee12a7 (首地址值)
		System.out.println(arr16[0]);  //输出 [Ljava.lang.String;@330bedb4 (首地址值)
		System.out.println(arr16[0][0]);  //输出 null
		
		//特殊情况:
		String[][] arr17 = new String[4][];
		System.out.println(arr17);  //输出 [[Ljava.lang.String;@2503dbd3 (首地址值)
		System.out.println(arr17[0]);  //输出 null
		//System.out.println(arr16[0][0]);   报错,错误原因”空指针异常“	
		
		//二维数组练习1:求和
		System.out.println("二维数组练习一:求和");
		int[][] arr18 = new int[][]{{3,6,9},{8,16},{1,3,5}};
		
		//sum记录总和
		int sum = 0;
		
		//使用嵌套循环实现累加效果
		for( int i = 0 ; i < arr18.length ; i++ ) {
			for( int j = 0 ; j < arr18[i].length ; j++ ) {
				sum += arr18[i][j];
			}	
		}
		
		//输出结果
		System.out.println("二维数组arr18的总和为:"+ sum);  //输出 51
		
		/*
		 *   二维数组练习2:
		 *  声明:int[] x,y[];在给 x,y变量赋值以后,以下选项允许通过编译的是:
		 *   其中变量x是一维数组,变量y是二维数组。
		 *   a) x[0] = y ; no
		 *   b) y[0] = x ; yes
		 *   c) y[0][0] = x; no
		 *   d) x[0][0] = y; no
		 *   e) y[0][0] = x[0]; yes
		 *   f) x = y; no
		 *   
		 *   提示:
		 *   一维数组: int [] x 或者 int x[]
		 *   二维数组:int [][] y 或者 int [] y[] 或者 int y[][]
		 */
		
		/*
		 * 二维数组练习3:使用二维数组打印一个10 行杨辉三角。
		 * 提示 :
		 * 1)第一行有 1 个元素 , 第 n 行有 n 个元素
		 * 2)每一行的第一个元素和最后一个元素都是 1
		 * 3)从第三行开始 , 对于非第一个元素和最后一个元素的元素。即:
		 * yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
		 */
			 
		System.out.println("二维数组练习3:使用二维数组打印一个10 行杨辉三角。");
		
		//声明一个外层元素为10的二维函数。
		int[][] yangHui = new int[10][];
		
		for (int i = 0 ; i < yangHui.length ; i++ ) {
			
			//给数组元素赋值
			yangHui[i] = new int[i+1];
			//杨辉三角的首元素和末元素都是1
			yangHui[i][0] = yangHui[i][i] = 1;  
			//给每一行的非首末元素赋值
			//(yangHui[i].length - 1)减一是为了不让赋值到最后一个元素。
			for (int j = 1 ; j < (yangHui[i].length - 1) ; j++) {
				yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];		
			}
			
			//打印杨辉三角
			for (int j = 0; j < yangHui[i].length; j++) {
				System.out.print(yangHui[i][j] + "\t");	
			}
			System.out.println();	
		}
		
		/* 
		 * 数组中涉及的常见算法:
		 * 1)数组元素的赋值 杨辉三角、回形数等(见上方例题)
		 * 2)求数值型 数组中元素 的最大值、最小值、平均数、总和等
		 * 3)数组的复制 、反转、查找 线性查找、二分法查找
		 * 4)数组元素 的 排序算法
		 */
		
		// 1)数组元素的赋值 杨辉三角、回形数等(见上方例题)
		// 例题:创建一个长度为 6 的 int 型数组,要求数组元素的值都在 1 30 之间,
		// 且是随机赋值。同时,要求元素的值各不相同。
		System.out.println("\n数组练习1:数组元素的赋值。");
		int[] arr19 = new int[6];
		for (int i = 0 ; i < arr19.length ; i++ ) {
			
			//给arr19赋值,值的范围为1-30之间的随机数。
			arr19[i] = (int) (Math.random() * 30) + 1;
			
			//在for循环内嵌套一个if判定,判断新赋的值与数组里面已有的值是否相同,如果相同就重新赋值
			for (int j = 0; j < i ; j++) {
				if ( arr19[i] == arr19[j] ) {
					i--;
					break;
				}	
			}	
		}
		
		//遍历数组
		System.out.print("数组arr19内的各项值为:");
		for (int i = 0; i < arr19.length; i++) {
			System.out.print(arr19[i] +"\t");
		}
		System.out.println();  //换行
		
		/* 
		 * 回形数格式方阵的实现
 		 * 从键盘输入一个整数(1~20)
		 * 则以该数字为矩阵的大小,把1,2,3…n*n 的数字按照顺时针螺旋的形式填入其中。
		 * 例如: 输入数字2,则程序输出: 1 2 
		 *  4 3 
		 * 输入数字3,则程序输出: 1 2 3 
		 *  8 9 4 
		 *  7 6 5 
		 * 输入数字4, 则程序输出: 
		 *  1   2   3   4 
		 *  12  13  14  5 
		 *  11  16  15  6 
		 *  10  9   8   7
		 */ 
		
		System.out.println("\n数组练习2:回形数格式方阵的实现。");
		System.out.println("请输入回形数格式方阵的行数:");
		int n = 0;
		n = scanner.nextInt();
		int[][] arr = new int[n][n];

		int count = 0; // 要显示的数据
		int maxX = n - 1; // x轴的最大下标
		int maxY = n - 1; // Y轴的最大下标
		int minX = 0; // x轴的最小下标
		int minY = 0; // Y轴的最小下标
		while (minX <= maxX) {
			for (int x = minX; x <= maxX; x++) {
				arr[minY][x] = ++count;
			}
			minY++;
			for (int y = minY; y <= maxY; y++) {
				arr[y][maxX] = ++count;
			}
			maxX--;
			for (int x = maxX; x >= minX; x--) {
				arr[maxY][x] = ++count;
			}
			maxY--;
			for (int y = maxY; y >= minY; y--) {
				arr[y][minX] = ++count;
			}
			minX++;
		}

		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < arr.length; j++) {
				String space = (arr[i][j] + "").length() == 1 ? "0" : "";
				System.out.print(space + arr[i][j] + " ");
			}
			System.out.println();
		}
		
		
		/* 
		 * 2)求数值型 数组中元素 的最大值、最小值、平均数、总和等
		 * 例题:定义一个int型的一维数组,包含 10 个元素,分别赋一些随机整数,
		 * 然后求出所有元素的最大值, 最小值,和值、平均值,并输出 出来 。
		 * 要求:所有随机数都是两位数。
		 * 提示;	
		 * [0,1) * 90 → [0,90) + 10 → [10,100) → [10,99]
		 * (int)(Math.random() * ( 99 - 10 + 1 ) + 10
		 */
		System.out.println("数组练习3:赋10 个元素,输出最大值, 最小值,和值、平均值。");
		
		int[] arr20 = new int[10];
		//记录大值:
		int maxValue = arr20[0];
		//记录小值:
		int minValue = 100;
		//记录平均值:
		int avfValue = arr20[0];
		//记录和值:
		int sum1 = 0;
		System.out.print("\n数组arr20中的值为:");
		for (int i = 0 ; i < arr20.length ; i++ ) {
			//赋值
			arr20[i] = (int)(Math.random() * (99-10+1)+10);	
			
			//遍历
			System.out.print(arr20[i] +"\t");
			
			//求最大值:
			if( maxValue < arr20[i] ) {
				maxValue = arr20[i];
			}
			//求最小值:
			if( minValue > arr20[i] ) {
				minValue = arr20[i];
			}
			//求和值:
			sum1 = sum1 + arr20[i];			
		}System.out.println();
		//求平均值:
		avfValue = sum1 / 10;
		System.out.println("数组中的最大值为:" + maxValue);
		System.out.println("数组中的最小值为:" + minValue);
		System.out.println("数组中的和值为:" + sum1);
		System.out.println("数组中的平均值为:" + avfValue);
			
		/* 
		 * 3)数组的复制 、反转、查找 线性查找、二分法查找
		 * (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 。
		 * 
		 */
		
		System.out.println("\n数组练习4:复制简单数组");
		//创建数组array1和array2
		int[] array1 = new int[]{2,3,5,7,11,13,17,19};
		int[] array2 = new int[array1.length];
		//将数组array1的值赋值给array2
		System.out.print("数组array1中的值为:");
		for ( int i = 0 ; i < array1.length ; i++) {
			array2[i] = array1[i];
			
			//遍历数组array1
			System.out.print(array1[i] +"\t");
		}
		for ( int j = 0; j < array2.length ; j++) {
			if ( j%2 == 0) {
				array2[j] = j;
			}
		}
		
		//3)数组的复制 、反转、查找 线性查找、二分法查找
		System.out.println("\n\n数组练习5:反转简单数组");
		for (int i = 0; i < (array1.length/2); i++) {
			
			int x = array1[i];
			array1[i] = array1[array1.length-i-1];
			array1[array1.length-i-1] = x;
		}
		
		System.out.print("数组array1反转后的值为:");
		for (int i = 0; i < array2.length; i++) {				
			//遍历数组array1
			System.out.print(array1[i] +"\t");		
		}
		
		//3)数组的复制 、反转、查找 线性查找、二分法查找
		//查找(又称搜索)
		//线性查找:
		System.out.println("\n\n数组练习6:线性查找,查找数组arr21中是否有 “C“ ");
		String[] arr21 = new String[]{"A","B","C","D"};
		String dest = "C";
		boolean isFlag = true;
		
		//遍历数组arr21
		System.out.print("数组arr21的值为:");
		
		for (int i = 0; i < arr21.length; i++) {
			System.out.print(arr21[i] +"\t");
		}
		
		for ( int i = 0 ; i < array1.length ; i++ ) {
	
			//搜索数组arr21中是否有“C”。
			if ( dest.equals(arr21[i]) ) {
				System.out.println("\n找到了指定元素,位置在第"+ (i+1) +"项\n");
				isFlag = false;
				break;
			}
		}
		
		if (isFlag) {
			System.out.println("很遗憾,在数组arr21中没有找到 “C” \n");
		}
		
		//3)数组的复制 、反转、查找 线性查找、二分法查找
		//二分法查找:(效率比线性查找快)
		//前提:所要查找的数组必须有序。
		System.out.println("\n\n数组练习7:二分法查找,查找数组arr22中是否有 “-34“ ");
		
		int[] arr22 = new int[] {-98,-34,-2,10,53,95,103,666,698,723};
		int dest1 = -34;
		int head = 0;  //初始的首索引
		int end = arr22.length - 1; //初始的末索引
		boolean isFlag1 = true;
		
		//遍历数组arr22
		System.out.print("数组arr22的值为:");
				
		for (int i = 0; i < arr22.length; i++) {
			System.out.print(arr22[i] +"\t");
		}
		
		while ( head <= end) {
			
			//取数组arr22中间项的位置
			int middle = (head + end)/2;
						
			//判断要寻找的值在中间项的什么位置
			if ( dest1 == arr22[middle] ) {
				System.out.println("\n找到了指定元素,位置在第"+ (middle+1) +"项\n");
				isFlag1 = false;
				break;
			}else if ( arr22[middle] > dest1 ) {
				end = middle - 1;
			}else { //这里相对于arr22[middle] < dest1
				head = middle + 1;
			}			
		}
		
		if (isFlag1) {
			System.out.println("很遗憾,在数组arr22中没有找到 “-34” \n");
		}
		
		/*
		 * 4)数组元素 的 排序算法
		 * 排序:假设含有 n 个记录的序列为 {R1,R2,...Rn)其相应的关键字序列为
		 * {K1,K2,...Kn)。将这些记录重新排序为 {Ri1,Ri2,... Rin)使得相应的关键
		 * 字值满足条 Ki1<=Ki2<=...<=Kin, 这样的一种操作称为排序。
		 * 通常来说,排序的目的是快速查找。
		 * 
		 * 衡量排序算法的优劣:
		 * 1)时间复杂度 :分析关键字的比较次数和记录的移动次数
		 * 2)空间复杂度: 分析排序算法中需要多少辅助内存
		 * 3)稳定性: 若两个记录 A 和 B 的关键字值相等,但排序后 A 、 B 的先后次序保
		 * 持不变,则称这种排序算法是稳定的。
		 * 
		 * 排序算法分类:内部排序 和 外部排序 。
		 * 1)内部排序 :整个排序过程不需要借助于外部存储器(如磁盘等),所有排
		 * 序操作都在内存中完成。
		 * 2)外部排序 :参与排序的数据非常多,数据量非常大,计算机无法把整个排
		 * 序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最
		 * 常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。
		 * 
		 * 十大内部排序算法
		 * 1)选择排序:直接选择排序、 堆排序
		 * 2)交换排序:冒泡排序 、 快速排序
		 * 3)插入排序:直接插入排序、 折半插入排序、 Shell 排序
		 * 4)归并排序
		 * 5)桶式排序
		 * 6)基数排序
		 * 
		 * 各种内部排序方法性能比较:
		 * 1)从平均时间而言 快速排序最佳。 但在最坏情况下时间性能不如堆排序和归并排序。
		 * 2)从算法简单性看 :由于直接选择排序、直接插入排序和冒泡排序的算法比较
		 * 简单,将其认为是 简单 算法。 对于 Shell 排序、堆排序、快速排序和归并排序
		 * 算法,其算法比较复杂,认为是复杂排序。
		 * 3)从稳定性看 :直接插入排序、冒泡排序和归并排序时稳定的;而直接选择排
		 * 序、快速排序、 Shell 排序和堆排序是不稳定排序
		 * 4)从待排序的记录数 n 的大小看 n 较小时,宜采用简单排序;而 n 较大时宜采
		 * 用改进排序。
		 * 
		 * 排序算法的选择:(见文章末图片)
		 * 1)若 n 较小 (如 n≤50)可采用 直接插入 或 直接选择排序 。
		 * 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直
		 * 接插入,应选直接选择排序为宜 。
		 * 2)若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排
		 * 序为宜。
		 * 3)若n较大,则应采用时间复杂度为 O(nlgn)的排序方法:快速排序、堆排序或
		 * 归并排序 。
		 */
		System.out.println("\n\n数组练习8:冒泡排序 ");
		
		int[] arr23 = new int[] {-98,-3,66,89,55,32,0,-65,88,100};
		
		//遍历数组arr23
		System.out.print("数组arr23的值为:");				
		for (int i = 0; i < arr23.length; i++) {
			System.out.print(arr23[i] +"\t");
		}System.out.println();
		
		for( int i = 0 ; i < arr23.length ; i++ ) {
			for(int j = 0; j < (arr23.length-i-1); j++) {
				if (arr23[j] > arr23[j+1]) {
					int temp = arr23[j];
					arr23[j] = arr23[j+1];
					arr23[j+1] = temp;
				}
			}	
		}
		
		//遍历数组arr23
		System.out.print("数组arr23的值为:");				
		for (int i = 0; i < arr23.length; i++) {
			System.out.print(arr23[i] +"\t");
		}System.out.println();
		
		/*
		 * 快速排序
		 * 介绍:
		 * 快速排序通常明显比同为O(nlogn) 的其他算法更快,因此常被采用,而且快
		 * 排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。可
		 * 见掌握快排的重要性 。
		 * 
		 * 快速排序(Quick Sort )由图灵奖获得者 Tony Hoare 发明,被列为 20 世纪十
		 * 大算法之一 ,是迄今为止所有内排序算法中速度最快的一种。冒泡排序的升
		 * 级版,交换排序的一种。快速排序的时间复杂度为 O(nlog(n)) 。
		 * 
		 * 排序思想:
		 * 1)从数列中挑出一个元素,称为“基准”(pivot)
		 * 2)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准
		 * 值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,
		 * 该基准就处于数列的中间位置。这个称为分区( partition )操作。
		 * 3)递归地( recursive )把小于基准值元素的子数列和大于基准值元素的子数列排序。
		 * 4)递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好
		 * 了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代
		 * (iteration )中,它至少会把一个元素摆到它最后的位置去 。
		 * 
		 * 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,
		 * 则分别对这两部分继续进行排序,直到整个序列有序。
		 */
		
//		System.out.println("\n\n数组练习9:快速排序 ");
//		
//		public class QuickSort {
//			private static void swap(int[] data, int i, int j) {
//				int temp = data[i];
//				data[i] = data[j];
//				data[j] = temp;
//			}
//
//			private static void subSort(int[] data, int start, int end) {
//				if (start < end) {
//					int base = data[start];
//					int low = start;
//					int high = end + 1;
//					while (true) {
//						while (low < end && data[++low] - base <= 0)
//							;
//						while (high > start && data[--high] - base >= 0)
//							;
//						if (low < high) {
//							swap(data, low, high);
//						} else {
//							break;
//						}
//					}
//					swap(data, start, high);
//					
//					subSort(data, start, high - 1);//递归调用
//					subSort(data, high + 1, end);
//				}
//			}
//			public static void quickSort(int[] data){
//				subSort(data,0,data.length-1);
//			}
//			
//			
//			public static void main(String[] args) {
//				int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
//				System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
//				quickSort(data);
//				System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
//			}
//		}
		
	}
}

排序

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值