Java第四课. 数组&算法应用&Debug

数组&算法应用&Debug

1.数组

1.1 数组的概念和作用
• 数组是一组类型相同的数据的集合;
• 也就是说,数组中可以存储多个数据,但是这些数据的类型必须相同;//不同会报错
• 数组能够作为数据的容器使用,把多个数据集中存储;
• 存储在数组中的数据,都有相应的索引值,可以方便获取或修改;
• 当需要同时保存多个类型相同的变量并进行处理时,可以考虑用数组,例如:多个人的成绩、多个员工的薪资……
1.2 Java的数组特性
• Java的数组是引用类型;
• 数组与类、接口、枚举、注解并列,是引用类型中的一种;
• Java的数组长度一经确定不能改变;  //重点
• 例如,一个数组的长度是10,那么最多能存10个数据,如果保存第11个就会出错;
• 数组在内存中是连续分配,所以读取速度快
1.3 数组元素
• 数组中存储的数据称为数组的元素(Element);
• 数组本身是引用类型,但是数组中的元素可以是基本数据类型,也
可以是引用类型;  //这点很重要
  • 也就是说,即可以有存储基本数据类型int的数组,也可以有存储引用类型String的数组,但是数组本身是引用类型;
• 数组中的元素有索引值,索引值从0开始;
  • 也就是说,如果一个数组的长度是10,那么索引值就是0-9,也就是第一个元素的索引值是0,第二个的索引值是1,以此类推,通过索引值可以方便访问元素;  //基础点
1.4 一维数组
1.41 一维数组的声明形式
数组元素类型[ ] 变量名称;
或
数组元素类型 变量名称[ ] ;
例如:
int[] a;int a[];
String[] s; 或 String s[]//很容易忘记
• 不论数组中元素是什么类型,以上声明形式都适用;
1.42 一维数组的初始化
第一种:数组元素类型[ ] 变量名称=new 数组元素类型[数组长度];
第二种:数组元素类型[ ] 变量名称=new 数组元素类型[]{用逗号隔开元素的具体值};
第三种:数组元素类型[ ] 变量名称= {用逗号隔开元素的具体值};
//第一种:数组元素类型[ ] 变量名称=new 数组元素类型[数组长度];
int[] array=new int[10];//在内存中开辟了一个连续的空间,长度为10的数组,数组元素默认值0
		
//第二种:数组元素类型[ ] 变量名称=new 数组元素类型[]{用逗号隔开元素的具体值};
int[] array2=new int[] {1,23,45};//数组中有3个元素
		
//第三种:数组元素类型[ ] 变量名称= {用逗号隔开元素的具体值};
int[] array3= {1,23,456};//数组中有3个元素
• 数组是引用类型,a保存数组的首地址,指向堆中数组的具体内容;
• 数组元素使用索引表示,如a[0]、a[1]...

在这里插入图片描述

1.43 数组的访问
数组是引用类型,数组名array保存的是数组的首地址,指向堆中数组的具体内容;
数组元素使用索引表示,索引从0开始如:array[0],array[1].....
语法:
数组变量名[索引];//索引从0开始,到长度-1

注意:如果访问数组的下标越界,会出现异常信息
//2.如何对数组中元素赋值
//格式:数组变量名[索引]=值;
array[0]=1; //为数组中第1个元素赋值
array[1]=22;//为数组中第2个元素赋值
array[2]=9; //为数组中第3个元素赋值
		
//3.如何访问数组中的元素
//格式:数组变量名[索引]
System.out.println("访问数组中的第一个元素:"+array[0]);
System.out.println("访问数组中的第2个元素:"+array[1]);
System.out.println("访问数组中的第3个元素:"+array[2]);
System.out.println("访问数组中的第10个元素:"+array[9]);//0
//System.out.println("越界:"+array[10]);//报异常,不能越界
1.44 数组的长度
使用数组变量名.length属性可以返回数组的长度;
//4.获取数组的长度
System.out.println("数组长度:"+array.length);//10
System.out.println("数组长度:"+array2.length);//3
1.45 数组的遍历
1.for循环
    
//5.遍历数组
System.out.println("**********方式1:for循环遍历数组***********");
//index索引从0开始到数组长度-1  ->9
for (int index = 0; index < array.length; index++){
	System.out.println(array[index]);
}
		
for(int i=0;i<array2.length;i++) {
	System.out.println(array2[i]);
}
2.增强for循环
    
System.out.println("**********方式2:foreach循环遍历数组***********");
/*for(数组元素的数据类型  变量名: 遍历的数组名 ) {
			
}*/
		
for(int  k: array ) {//从array中遍历每一个元素赋值给k
	System.out.println(k);	
}
1.46 数组的排序
java API中有个类Arrays.定义了大量的 sort(),可以对数组中的元素进行排序;

import java.util.Arrays;

public class TestArray_01 {

	public static void main(String[] args) {
		//定义一个整数数组
		int [] intArray= {59,23,122,44,555,3,0,-1};
		
		//直接遍历
		for (int i : intArray) {
			System.out.print(i+" ");//59 23 122 44 555 3 0 -1 
		}

		System.out.println();
		//使用api中的Arrays类的sort()可以排序
		Arrays.sort(intArray);
		//再输出
		for (int i : intArray) {
			System.out.print(i+" ");//从小到大  -1 0 3 23 44 59 122 555 
		}
		System.out.println();
        
		//定义一个字符数组
		char[] charArray= {'6','A','Z','a','7'};
		for (char c : charArray) {
			System.out.print(c+" ");
		}
		System.out.println();
		Arrays.sort(charArray);
		
		for (char c : charArray) {
			System.out.print(c+" ");//6 7 A Z a 
		}
	}
    
}
1.5 数组&常见算法问题
1.51 和和平均值(累加,总和除以个数)
1.	从控制台接收5个学生的java成绩,求和和平均分;
public class TestArray{

	public static void main(String[] args) {
		// 从控制台接收5个学生的java成绩,求和和平均分;
		
		
		//1.先定义一个数组存放学生的成绩
		double[] score=new double[5];
		double sum=0;
		
		//2.从控制台输入成绩存入数组中
		Scanner scanner=new Scanner(System.in);
		for (int i = 0; i < score.length; i++) {
			//提示
			System.out.println("请输入第"+(i+1)+"个学生的java成绩:");
			//接收
			score[i]=scanner.nextDouble();
			//累加求和
			sum+=score[i];
		}
		/*for (double d : score) {
			//接收
			d=scanner.nextDouble();
			//累加求和
			sum+=d;
		}*/
		System.out.println("总成绩:"+sum+",平均成绩:"+sum/(score.length));

	}

}
1.52 最值(最大值 最小值)
思考:
	假设第一个元素的值为最大,然后接下来用相邻的值和第一个值比较,保留大的那个值;再用这个值和下一个相邻的元素比较,保留最大的;以此类推 ;直到最后一个元素,得到了所有数字中的最大值;
public class TestArray {

	public static void main(String[] args) {
		
		//比较最值问题
		
		//1.先定义一个数组存放学生的成绩
		double[] score=new double[5];
		//2.从控制台输入成绩存入数组中
		Scanner scanner=new Scanner(System.in);
		for (int i = 0; i < score.length; i++) {
			//提示
			System.out.println("请输入第"+(i+1)+"个学生的java成绩:");
			//接收
			score[i]=scanner.nextDouble();
		}
        
		//方式1:直接使用工具类Arrays的sort()
		/*Arrays.sort(score);
		System.out.println("最低分:"+score[0]);
		System.out.println("最高分:"+score[score.length-1]);*/
		
		//方式2:
		//假设:数组中 第一个元素就是最大值/最小值
		double max=score[0];
		double min=score[0];//如果放在循环里面每次循环开始又会重新赋值
        
		//遍历数组,一一比较
		for (int i = 1; i < score.length; i++) {// 2  5 6 1 4
			if (score[i]>max) {
				max=score[i];  //交换
			}
			if (score[i]<min) {
				min=score[i];  //交换
			}
		}
		System.out.println("最高分:"+max);
		System.out.println("最低分:"+min);
	}

}
1.53 查找
String[] names={“小白”, “小宏”, “小兰”, “小黑”, “小绿”, “小白”};
//查询 数组中是否包含特定的某个元素,比如是否包含”小白”,要给出提示,如果存在,输出在哪个位置找到了,如果不存在,就提示不存在 
String find=”小白”
public class TestArray {

	public static void main(String[] args) {
		// 查找
		String[] names={"小白", "小黑", "小绿", "小红", "塞班", "塞班"};
        boolean flag=false;//表示没找到
        String find="小红2";
        for (int i = 0; i < names.length; i++) {
			if (names[i].equals(find)) {
				//有找到
				System.out.println("在第"+(i+1)+"个位置上找到了"+find);
				flag=true;//找到了
			}
		}
        
        //在循环判断提示信息
        if (!flag) {  //值为false执行
			System.out.println("没找到"+find);
			
		}
	}
}
1.54 插入算法(了解)
在一个已经按照特定顺序排好的数组中,我们要插入一个新的元素进来,要求,插入新的元素之后,数组元素依然是有序的.
int array[]={1,3,5,7,9,0}
public class Test {

	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		//1.定义一个有序数组,长度为6,最后一个数0表示空位置,后面插入会用到
		int[] arr = {1,3,5,7,9,0};
		//2.数组中第六个元素的位置
		int position=5;
		System.out.println("请输入要插入的数:");//6
		int insert=scanner.nextInt();
		
		//3.遍历数组,和插入的元素进行比较,最后一个元素不用参加比较
		for (int i = 0; i < arr.length-1; i++) {
			//从第一个元素开始比较,判断大于插入的值
			if (arr[i]>insert) {
				//4.记录大于insret值的下标
				position=i; //3
				break; //退出循环
			}
		}
		
		//5.开始移动元素,把位置腾出来给插入的值,从最后一个元素开始,倒着便遍历数组
		for (int i = arr.length-1; i >position; i--) {
			//将前面的数赋值给后面,范围要大于标记刚刚标记的位置
			arr[i]=arr[i-1];
		}
		//6.将插入的元素放到标记位置
		arr[position]=insert;//array[3]=6
		
		for (int i : arr) {
			System.out.print(i+" ");
		}
		scanner.close();

	}

}
1.55 排序算法
冒泡排序: 
int[] arr ={12,7,-1,8,99}
希望以上一组数能够按照一定的顺序(从大到小/从小到大)重新排列;
相邻的两个元素依次比较,根据比较条件,来交换位置;

1.第一轮开始:比较了4,结果是得到了5个数中的最大值
	127,>比较,如果条件为真,则交换两个元素
    12和下一个相邻元素 12>-1, 则交换两个元素
    			....
2.第二轮开始:比较了3,结果是得到了剩下4个数中的最大值;
				...
3.第三轮开始: 比较了2,结果是得到了剩下3个数中的最大值;
4.第四轮开始: 比较了1,结果是得到了剩下2个数中的最大值;

总结:5个数字,比较了4;
每一轮内部比较了几次: 4 3 2 1
满足条件我们做什么?交换两个相邻的元素

嵌套循环; 外控制比较的轮数(长度-1) ;内循环控制的是每轮比较的次数(长度-i-1) ; 
i是外循环变量; 内循环中比较相邻的元素( 使用内循环变量作为下标 array[j]>array[j+1]) ;
结果 应该是从小到大;
public class Test{

	public static void main(String[] args) {
		Scanner sc =new Scanner(System.in);
		
		float[] arr =new float[5];  
		for (int i = 0; i <5; i++) {
			System.out.println("请输入第"+(i+1)+"个数:");
			arr[i] = sc.nextFloat(); 

		}
		//定义中间变量
		float temp=0;
		//外层循环,定义比较的轮数(长度-1) (4)
		for (int i = 0; i < arr.length-1; i++) { //i的取值范围为0,1,2,3
			//内层循环,定义每轮比较的次数(长度-1,长度-2...1) (4,3,2,1)
			 for (int j = 0; j < arr.length-i-1; j++) { //j的取值范围为0,1,2,3
				 //每次进行比较的两个元素都是与内循环j有关的,i代表比较轮数,每次内循环值不变
				if (arr[j]>arr[j+1]) {
					temp=arr[j];
					arr[j]=arr[j+1];
					arr[j+1]=temp;	
				}
			}
		}
		for (float f : arr) {
			System.out.println(f);
		}
	}
}
1.6 二维数组:
二维数组,在内存中的结构和一维数组是一致的;但是我们可以将其理解为一个平面结构;
• 如果一个数组中存储数据结构如下所示,元素是一维数组,称为二维数组;

在这里插入图片描述

• 其中,第0个元素是数组{67,78,54},第1个元素是数组{89,12};
二维数组可以理解成一个表格:有行有列,行有下标,列也有下标;
1.61 定义和赋值
数组元素类型[ ][ ] 变量名称=new 数组元素类型[一维长度] [二维长度];

数组元素类型[ ][ ] 变量名称=new 数组元素类型[行数] [列数];

如果同时确定一维和二维的长度,则表示数组的元素是等长的一维数组
//构建一个5行6列的二维数组,这个二维数组中包含5个一位数组,每个一维数组的长度是6(里面包含6个元素)
int[ ][ ] array=new int[5] [6];

如果数组元素不是等长的一维数组,可以不指定二维长度;
int[ ][ ] array=new int[5] [];
public class TestArray {

	public static void main(String[] args) {
		//1.定义一个二维数组,二维长度固定
		int[][] array01=new int[3][4];
		
		//定义一个二维数组,二维长度不固定
		int[][] array02=new int[3][];
		
		//2.对二维数组的元素访问
        //访问第一个一维数组中的第一个元素,默认值=0
		System.out.println(array01[0][0]);
        //访问第一个一维数组中的第2个元素,0
		System.out.println(array01[0][1]);
		
		//3.对二维数组的元素赋值
		array01[0][0]=10;
		array01[0][1]=20;
		array01[0][2]=30;
		array01[0][3]=40;
		array01[1][0]=50;
		array01[2][3]=1000;
		
		//System.out.println(array01[3][3]);//报错
		
		//4.获取二维数组的长度
		System.out.println("一维数组的数量:"+array01.length);//3
		System.out.println("一维数组的二维长度:"+array01[0].length);//4
		System.out.println("一维数组的二维长度:"+array01[1].length);//4
		
		//5.遍历二维数组
		for(int i=0;i<array01.length;i++) {//一维长度
			for (int j = 0; j < array01[i].length; j++) {//array01[i]一维数组
				System.out.print(array01[i][j]+"\t");
			}
			System.out.println();
		}
	}

}

在这里插入图片描述

1.62 案例:杨辉三角
思考:(i)(j) 第一列值为1,以及每一行的最后一列,if(i==j || j==0)
Array[i][j]=array[i-1][j]+ array[i-1][j-1]
1(0,0)
1(1,0)1(1,1)
12(2,1)1(2,2)
1331(3,3)
14641(4,4)
public class TestArray {

	public static void main(String[] args) {
		//定义一个二维数组
		int[][] array=new int[20][20];
		
		//控制行
		for (int i = 0; i < array.length; i++) {
			//控制列->打印数字
			for (int j = 0; j <=i; j++) {
				//先把1解决掉
				if(i==j || j==0) {
					array[i][j]=1;
				}else {
					array[i][j]=array[i-1][j]+ array[i-1][j-1];
				}
				System.out.print(array[i][j]+"\t");
			}
			
			//一行的结束
			System.out.println();
		}

	}

}
练习:
1.	实现等腰三角形的杨辉三角  [5][]
//这种方法只确定了二维数组的行数,所以列数需要根据行数进行初始化,等腰三角形还需要确定每行要打印的空格数
      /* 空格数: 第一行 :i=0,空格数4个(0+4)
				第二行 :i=1,空格数3个(1+3)
				第三行 :i=2,空格数2个(2+2)
				第四行 :i=3,空格数1个(1+3)
				所以空格数与当前行数的总和=数组长度-1
				*/
public class Test_how1 {

	public static void main(String[] args) {
		
		//定义一个二维数组,二维长度不固定
		int[][] arr=new int[20][];
		//1.控制行
		for (int i = 0; i < arr.length; i++) {
			//定义i+1个内存空间 ,所对应的就是第i+1行有i+1个元素。
			arr[i]=new int[i+1];
			//2.打印每一行空格
			for (int j = 0; j < arr.length-1-i; j++) {
                //三个空格,这里6必须是空格的倍数
				System.out.print("   ");
			}
			//3.控制列
			for (int j = 0; j <=i; j++) {
				//判断条件
				if (i==j || j==0) {
					arr[i][j]=1;
				}else {
					arr[i][j]=arr[i-1][j]+arr[i-1][j-1];
				}
                //以6位整数的形式输出
				System.out.printf("%6d",arr[i][j]);
			}
			//4.换行
			System.out.println("");
		}
	}
}
2.	定义二维数组,统计班级5个学生的Java,C#,Python课程的成绩,并求每门课程的平均分;
数组定义:  double score[][] = new double[3][5];

在这里插入图片描述

public class TestArray02 {

	public static void main(String[] args) {
		//1.定义一个二维数组
		double score[][]=new  double[3][5];
		Scanner scanner=new Scanner(System.in);
		for (int i = 0; i < score.length; i++) {
			//定义一个变量先求和
			double sum=0;
			System.out.println("请输入第"+(i+1)+"门课程的成绩:");
			//5个学生的成绩
			for (int j = 0; j < score[i].length; j++) {
				System.out.println("请输入第"+(j+1)+"个学生的成绩:");
				score[i][j]=scanner.nextDouble();
				sum+=score[i][j];
			}
			System.out.println("第"+(i+1)+"门课程的平均成绩:"+sum/5);
		}
		scanner.close();
	}

}

2. Debug

2.1 设置断点,右键选择 debug as

在这里插入图片描述

2.2 调试界面:

在这里插入图片描述

2.3 停止调试

在这里插入图片描述

2.4 小球落地
1.一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?
第10次落地反弹多高?(DEBUG)
public class Test {

	public static void main(String[] args) {
		//定义一个变量保存每次落地后弹起的高度
		double height=100;
		double sum=100;
		//循环变量
		int i=1;
		while(i<=10) {
		    //每次落地后反跳回原高度的一半
			height=height/2;
			//System.out.println("第"+i+"次落地时,弹起的高度为:"+height+"m");
			i++;//2
			if (i<=10) {//弹起来9次
                //height*2每次弹起来跟落下的距离相等
			    sum=sum+height*2; 
			   // System.out.println("第"+i+"次落地时,经过的路径长度为:"+sum+"m");
			}
		}
		System.out.println("第10次落地时,弹起的高度为:"+height+"m");
		System.out.println("第10次落地时,经过的路径长度为:"+sum+"m");
	}

}
2.5 猴子吃桃
	猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个 ;第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。请使用forwhile分别处理;
  分析:  一共吃了九天;倒着推理;10天早上开始:   没吃,  19天早上:   没吃,  (1+1)*2=>48天早上开始:   没吃,  (4+1)*2 =>10
     …
     第1天早上,摘了,还没吃  (?+1)*2 =>

  以上的分析可以得到:
1.	循环执行几次;
2.	计算桃子个数的表达式  (?+1)*2
//这题循环的天数倒着递减容易理解
public class Test {

	public static void main(String[] args) {
		// 1.循环执行几次?9次  从9天开始(第10天没吃到),到第1天结束
		// 2.计算桃子的公式:(?+1)*2
		// 3.定义一个变量,存储桃子总和
		int sum=1;//第10天剩一个
		for (int day = 9; day >=1; day--) {
			sum=(sum+1)*2;
			//System.out.println("第"+day+"天没吃,一共有:"+sum+"个桃子");
		}
		System.out.println("第1天没吃,一共有:"+sum+"个桃子");
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值