循环结构
1、定义:
在循环条件满足的情况下,反复执行特定代码的功能。
2、分类:
- for循环
- while循环
- do-while循环
3、循环语句的四个组成部分:
5.4 for 循环
1、格式:
2、执行过程:
当循环条件 ② 不满足的时候退出循环结构。
程序举例:
/*
For循环结构的使用:
一、循环结构的四个要素:
① 初始化条件,只在for循环内有效
② 循环条件
③ 循环体
④ 迭代条件
二、for循环结构
for(①初始化条件;②循环条件;④迭代条件)
{
③循环体
}
执行过程:① - ② - ③ - ④ - ② - ③ - ④ - …… - ②
*/
class ForTest
{
public static void main(String[] args)
{
//遍历100以内的偶数
for (int i=0; i<=100; i++){
if (i % 2 == 0){
System.out.print(i + "\t");
}
}
}
}
执行结果:
D:\MyDownloads\JAVA\my_java_code\day04>java ForTest
0 2 4 6 8 10 12 14
16 18 20 22 24 26 28 30
32 34 36 38 40 42 44 46
48 50 52 54 56 58 60 62
64 66 68 70 72 74 76 78
80 82 84 86 88 90 92 94
96 98 100
3、说明:
4、课后习题:
4.1 课后习题1:
程序:
/*
编写程序从1循环到150,并在每行打印一个值,另外在每个3的倍数行上打印出“foo”,
在每个5的倍数行上打印“biz”,在每个7的倍数行上打印输出“baz”。
*/
class ForTest1
{
public static void main(String[] args)
{
for (int i=1; i<=150; i++){
System.out.print(i+ " ");
// if (i % 3 == 0){
// System.out.println("foo");
// }else if(i % 5 == 0){
// System.out.println("biz");
// }else if(i % 7 == 0){
// System.out.println("baz");
// }else{
// System.out.println();
// }
if (i % 3 == 0){
System.out.print("foo ");
}
if(i % 5 == 0){
System.out.print("biz ");
}
if(i % 7 == 0){
System.out.print("baz ");
}
//换行
System.out.println();
}
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day04>java ForTest1
1
2
3 foo
4
5 biz
6 foo
7 baz
8
9 foo
10 biz
11
12 foo
13
14 baz
15 foo biz
16
17
18 foo
19
20 biz
21 foo baz
22
23
24 foo
25 biz
26
27 foo
28 baz
29
30 foo biz
31
32
33 foo
34
35 biz baz
36 foo
37
38
39 foo
40 biz
41
42 foo baz
43
44
45 foo biz
46
47
48 foo
49 baz
50 biz
51 foo
52
53
54 foo
55 biz
56 baz
57 foo
58
59
60 foo biz
61
62
63 foo baz
64
65 biz
66 foo
67
68
69 foo
70 biz baz
71
72 foo
73
74
75 foo biz
76
77 baz
78 foo
79
80 biz
81 foo
82
83
84 foo baz
85 biz
86
87 foo
88
89
90 foo biz
91 baz
92
93 foo
94
95 biz
96 foo
97
98 baz
99 foo
100 biz
101
102 foo
103
104
105 foo biz baz
106
107
108 foo
109
110 biz
111 foo
112 baz
113
114 foo
115 biz
116
117 foo
118
119 baz
120 foo biz
121
122
123 foo
124
125 biz
126 foo baz
127
128
129 foo
130 biz
131
132 foo
133 baz
134
135 foo biz
136
137
138 foo
139
140 biz baz
141 foo
142
143
144 foo
145 biz
146
147 foo baz
148
149
150 foo biz
注:if - esle if - else 分支结构只能运行一个分支语句。
4.2 课后习题2:
程序:
/*
题目:输入两个正整数m和n,求其最大公约数和最小公倍数。
比如:12和20的最大公约数是4,最小公倍数是60。
说明:break关键字的使用
*/
import java.util.Scanner;
class ForTest
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("请输入第一个正整数:");
int m = scan.nextInt();
System.out.println("请输入第二个正整数:");
int n = scan.nextInt();
//获取最大公约数
int min = (m > n)? n:m; //获取两个数中的较小值
//2、遍历,从大到小遍历
for (int i=min;i>=1 ;i-- )
{
if (m%i==0 && n%i==0)
{
System.out.println(m +" 和 "+ n +" 的最大公约数为: " + i);
break; //一旦在循环中执行到break,就跳出循环。
}
}
//获取最小公倍数
//1、获取两个数中的较大值
int max = (m > n)? m:n;
//2、遍历,从小到大遍历
for (int i=1;i<=min ;i++ )
{
int num = max*i;
if (num % min ==0)
{
System.out.println(m +" 和 "+ n +" 的最大公倍数为: " + num);
break;
}
}
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day05>java ForTest
请输入第一个正整数:
12
请输入第二个正整数:
20
12 和 20 的最大公约数为: 4
12 和 20 的最大公倍数为: 60
注:
- 从键盘输入时,提示语句应该在输入类方法上方。
- 遍历的时候,从小到大遍历迭代部分为 i++,从大到小遍历迭代部分为 i- - 。
5.5 while 循环
1、格式:
2、执行过程:
程序举例:
class WhileTest
{
public static void main(String[] args)
{
//遍历100以内的所有偶数
int i = 1;
while (i <= 100)
{
if (i % 2 ==0)
{
System.out.println(i);
}
i++;
}
//i出了循环仍然有用
System.out.println();
System.out.println(i);
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day05>java WhileTest
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
48
50
52
54
56
58
60
62
64
66
68
70
72
74
76
78
80
82
84
86
88
90
92
94
96
98
100
101
3、说明:
- 写while循环千万不要丢了迭代条件。一旦丢了,就可能导致死循环!
- 我们写程序,要避免死循环。
- while 循环和 for 循环可以相互转化的!
- 区别:for 循环和 while 循环的初始化条件部分以及迭代部分的作用范围不同,while循环定义的迭代体出了循环仍有用,for 循环定义的迭代体出了循环就没用了。
5.6 do-while 循环
1、格式:
2、执行过程:
注:do-while循环的循环条件部分最后执行。
程序举例:
class DoWhileTest
{
public static void main(String[] args)
{
//遍历100以内的偶数并计算所有偶数的和及偶数的个数
int count = 0; //记录偶数的个数
int sum = 0; //记录所有偶数的和
int num = 1;
do
{
if (num % 2 == 0)
{
sum += num;
count++;
System.out.println(num);
}
num++;
}
while (num <= 100);
System.out.println("偶数总和为:" + sum);
System.out.println("偶数个数为:" + count);
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day05>java DoWhileTest
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
48
50
52
54
56
58
60
62
64
66
68
70
72
74
76
78
80
82
84
86
88
90
92
94
96
98
100
偶数总和为:2550
偶数个数为:50
3、说明:
- do-while 循环至少会执行一次循环体。
- 开发中一般使用 for 和 while,使用 do-while 较少。
4、循环结构综合例题(包括 for 循环、while 循环):
程序:
import java.util.Scanner;
class XunhuanTest
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int positive = 0,negative = 0; //记录正数和负数的个数
for (; ; ) // while(true)
{
System.out.println("请输入一个整数!");
int num = scan.nextInt();
if (num > 0)
{
positive++;
}else if (num < 0)
{
negative++;
}else{
break; //一旦执行到break,就跳出循环。
}
}
System.out.println("输入的数中正数的个数为:" + positive + ",输入的数中负数的个数为:" + negative);
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day05>java XunhuanTest
请输入一个整数!
2
请输入一个整数!
4
请输入一个整数!
6
请输入一个整数!
8
请输入一个整数!
10
请输入一个整数!
-2
请输入一个整数!
-5
请输入一个整数!
0
输入的数中正数的个数为:5,输入的数中负数的个数为:2
注:
- 不在循环条件部分闲置次数的结构:for(; ; ) 或 while(true)
- 结束循环的方式有几种?
方式一:循环条件部分返回false
方式二:在循环体中,执行break - 最简单“无限” 循环格式:while(true) , for(; ; ),无限循环存在的原因是并不知道循环多少次,需要根据循环体内部某些条件,来控制循环的结束。
5.7 嵌套循环
1、定义:
将一个循环结构A声明在另一个循环结构B的循环体中,就构成了嵌套循环。
外层循环:循环结构B
内层循环:循环结构A
2、说明:
- 内层循环结构遍历一次,相当于外层循环只执行了一次。
- 假设外层循环结构执行m次,内层循环结构执行n次,此时内层循环的循环体一共执行了 m*n 次
3、程序举例:
class ForWhileTest
{
public static void main(String[] args)
{
//******
for (int i = 1;i<=6 ;i++ )
{
System.out.print('*');
}
System.out.println();
System.out.println();
/*
******
******
******
******
*/
for (int j = 1;j<=4 ;j++ )
{
for (int i = 1;i<=6 ;i++ )
{
System.out.print('*');
}
System.out.println();
}
System.out.println();
System.out.println();
/* i(行号) j(*的个数)
* 1 1
** 2 2
*** 3 3
**** 4 4
*/
for (int i = 1;i<=4 ;i++ )
{
for (int j = 1;j <= i;j++ )
{
System.out.print('*');
}
System.out.println();
}
System.out.println();
System.out.println();
/* i(行号) j(*的个数) 规律:i+j = 5,换句话说:j = 5 - i;
**** 1 4
*** 2 3
** 3 2
* 4 1
*/
for (int i = 4;i >= 1;i--)
{
for (int j = 1;j <= i;j++ )
{
System.out.print('*');
}
System.out.println();
}
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day05>java ForWhileTest
******
******
******
******
******
*
**
***
****
****
***
**
*
4、课后习题:
4.1 九九乘法表
/*
嵌套循环的应用1:
输出九九乘法表
1*1=1
2*1=2 2*2=4
……
9*1=9 9*2=18 …… 9*9=81
*/
class ForWhileTest1
{
public static void main(String[] args)
{
for (int i = 1;i <= 9 ;i++ )
{
for (int j = 1;j <= i;j++ )
{
int sum = i*j;
System.out.print(i + "*" + j + "=" + sum + "\t");
//System.out.print(i + "*" + j + "=" + (i*j) + "\t");
}
System.out.println();
}
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day05>java ForWhileTest1
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
4.2 100以内的所有质数
1、原始版本:
/*
嵌套循环的应用2:
输出100以内的所有质数
质数:素数,只能被1和它本身整除的自然数。--->从2开始到i-1为止,都不能被这个数整除
*/
class ForWhileTest2
{
public static void main(String[] args)
{
int count = 0; //设置一个计数器,计算这个数能整除的数字有几个,小于等于2个就是质数
for (int i = 1;i <= 100;i++ ) //遍历100以内的数
{
for (int j = 1;j <= i;j++ ) //i除以j
{
if (i % j == 0)
{
count++;
}
}
if (count <= 2)
{
System.out.println(i);
}
count = 0; //重置计数器
}
}
}
class ForWhileTest3 //宋老师版本
{
public static void main(String[] args)
{
boolean isFlag = true; //设置一个标志
for (int i = 1;i <= 100;i++ ) //遍历100以内的数
{
for (int j = 2;j < i;j++ ) //i除以j
{
if (i % j == 0)
{
isFlag = false;
}
}
if (isFlag == true)
{
System.out.println(i);
}
isFlag = true; //重置标志符
}
}
}**
2、优化版本(数字遍历方面 内层循环减少遍历次数)
class ForWhileTest4 //宋老师版本
{
public static void main(String[] args)
{
//获取当前时间距离1970-01-01 00:00:00的毫秒数
long start = System.currentTimeMillis();
boolean isFlag = true; //设置一个标志
for (int i = 1;i <= 100;i++ ) //遍历100以内的数
{
for (int j = 2; j <= Math.sqrt(i) ;j++ ) //i除以j
//优化2:针对本身是质数的是有效的,质数只用算一半的一半,中心位置是根号i
{
if (i % j == 0)
{
isFlag = false;
//break; //优化1:只对本身非质数的自然数是有效的。
}
}
if (isFlag == true)
{
System.out.println(i); //另外,系统输出特别占用时间,这里可以换成计数器,记录有几个质数,也会节省运行时间
}
isFlag = true; //重置标志符
}
//获取当前时间距离1970-01-01 00:00:00的毫秒数
long end = System.currentTimeMillis();
System.out.println("所花费的时间为:" + (end - start));
}
}
3、高级优化版本(不用设置标志,直接用 continue label 结束外层循环的当次循环)
class ForWhileTest5 //宋老师版本
{
public static void main(String[] args)
{
//获取当前时间距离1970-01-01 00:00:00的毫秒数
long start = System.currentTimeMillis();
boolean isFlag = true; //设置一个标志
label:for (int i = 1;i <= 100;i++ ) //遍历100以内的数
{
for (int j = 2; j <= Math.sqrt(i) ;j++ )
//i除以j,优化2:针对本身是质数的是有效的,质数只用算一半的一半,中心位置是根号i
{
if (i % j == 0)
{
continue label;
}
}
System.out.println(i);
//另外,系统输出特别占用时间,这里可以换成计数器,记录有几个质数,也会节省运行时间
}
//获取当前时间距离1970-01-01 00:00:00的毫秒数
long end = System.currentTimeMillis();
System.out.println("所花费的时间为:" + (end - start));
}
}
4、运行结果(所有版本的运行结果都是一样的):
找出10000以内质数的运行时间(100以内差别太小看不出来):
优化前:19609ms
优化一:12195ms
优化二:1433ms
高级优化:754ms
D:\MyDownloads\JAVA\my_java_code\day05>java ForWhileTest3
1
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
5.8 特殊关键字的使用:break、continue
1、说明:
- break 只能用于 switch语句 和 循环语句 中。
- continue 只能用于循环语句中。
- 二者功能类似,但continue是终止本次循环,break是终止本层循环。
- break、continue之后不能有其他的语句,因为程序永远不会执行其后的语句,如果后面有其他语句,否则编译不通过。
- 标号语句必须紧接在循环的头部。标号语句不能用在非循环语句的前面。
- 很多语言都有goto语句,goto语句可以随意将控制转移到程序中的任意一条语句上,然后执行它。但使程序容易出错。Java中的break和continue是不同于goto的。
2、程序举例:
class BreakContinueTest
{
public static void main(String[] args)
{
for (int i =1 ;i <= 10 ;i++ )
{
if (i % 4 == 0)
{
//break; //1 2 3
continue; //1 2 3 5 6 7 9 10
}
System.out.print(i);
}
System.out.println( "\n" );
//*************************************************
label:for (int i = 1;i <= 4;i++ )
{
for (int j = 1;j <= 10;j++ )
{
if (j % 4 == 0)
{
//break; //默认跳出包裹此关键字最近的一层循环
//continue;
//break label; //结束指定标识的一层循环结构
continue label;
}
System.out.print(j);
}
System.out.println();
}
}
}
运行结果:
D:\MyDownloads\JAVA\my_java_code\day05>java BreakContinueTest
123567910
123123123123
写在最后:
衡量一个功能代码的优劣:
- 正确性
- 可读性:注释要清晰
- 健壮性;对所有可能出现的情况是否都考虑在内了
- 高效率与低存储:时间复杂度、空间复杂度(衡量算法的好坏)