打乱有序的数组
随机生成整数
Random random=new Random();
random.nextInt(x);
不带参数的random.nextInt(),会生成所有有效的整数(包含正数,负数,0)
带参的random.nextInt(x),会生成一个范围在0~x(不包含x)内的任意正整数
生成一个[min,max]范围的整数,random.nextInt(max-min+1)+min
方法一
随机生成两个下标进行位置交换,利用for循环交换次数为数组长度一半
public static void outOrder(int arr[]){
Random random=new Random();
for(int i=0;i<arr.length/2;i++){ //遍历每一个数组小标
//随机产生两个下标值
int index1= random.nextInt(arr.length);
int index2= random.nextInt(arr.length);
int tmp=arr[index1];//将两个下标的数据值交换
arr[index1]=arr[index2];
arr[index2]=tmp;
}
System.out.println("打乱后的数组:"+ Arrays.toString(arr));
}
方法二
自定义下标交换规则,每次两个下标的数据值交换,交换次数数组长度一半
public static void outOrder(int arr[]){
Set<Integer> indexNum=new HashSet<>(); //检查下标是否被交换过
for(int i=0;i<arr.length;i++){ //遍历每一个数组小标
int index=Math.abs((i+arr[i]))%arr.length; //下标变化按一定规则改变
while (true){
if (indexNum.contains(index)) //判断新下标值是否已被占用
index=(index+1)%arr.length; //若被占用,则寻找未被占用的下标
else{
indexNum.add(index); // 生成的下标若未被占用,则放入集合中,打上标记
indexNum.add(i);
break;
}
}
int tmp=arr[i];//将两个下标交换
arr[i]=arr[index];
arr[index]=tmp;
}
System.out.println("打乱后的数组:"+ Arrays.toString(arr));
}
算法的基本结构
顺序结构、分支结构、循环结构
任何复杂程序都由"顺序结构"、“分支结构”、"循环结构"组成
分支结构
if、switch
if if(boolean){语句块}
if…else if(boolean){语句块}else{语句块}
if…else if… if(boolean){语句块}else if(boolean){语句块}else{语句块}
switch…case
switch(N){
case 值1:{语句块1;break; }
case 值2:{语句块2;break; }
case 值3:{语句块3;break; }
…
default: {语句块;break;}
}
分数判断等级
if…else if…
public static void judgeNum(int num){
if(num<60)
System.out.println("E");
else if (num<70)
System.out.println("D");
else if(num<80)
System.out.println("C");
else if(num<90)
System.out.println("B");
else
System.out.println("A");
}
switch…case
public static void judgeNum1(int num){
//[90,99]/10=9...[60,70]/10=6
switch (num/10){
case 10:case 9:{ //表示不同的值运行相同的语句块,可合并
System.out.println("A");
break;
}
case 8:{
System.out.println("B");
break;
}
case 7:{
System.out.println("C");
break;
}
case 6:{
System.out.println("D");
break;
}
default:{
System.out.println("E");
break;
}
}
输入年月判断月的天数
switch…case
Scanner scan=new Scanner(System.in);
System.out.println("请输入年份");
int year=scan.nextInt();
System.out.println("请输入月份");
int mouth=scan.nextInt();
switch (mouth){
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
System.out.println(year+"年的"+mouth+"月份有"+31+"天");
break;
case 4: case 6: case 9: case 11:
System.out.println(year+"年的"+mouth+"月份有"+30+"天");
break;
case 2:
if(year%4==0 && year%100!=0 || year%400==0)
System.out.println(year+"年的"+mouth+"月份有"+29+"天");
else
System.out.println(year+"年的"+mouth+"月份有"+28+"天");
break;
default:
System.out.println("输入有误");
break;
三目运算
int arr[]={31,28,31,30,31,30,31,31,30,31,30,31};
arr[1]=!(y%4==0&&y%100!=0||y%400==0)?28:29;
System.out.println(y+"年的"+m+"月份有"+(arr[m-1])+"天");
分支语句嵌套
分支语句的嵌套可以是:if与if 、if与switch、switch与if、switch与switch
输入性别、年龄,判断是否符合法定结婚年龄
switch(sex){
case 0:
if(age<0)
System.out.println("年龄不合法");
else {
if(age<22)
System.out.println("未达到");
else
System.out.println("达到");
}
break;
case 1:
if(age<0)
System.out.println("年龄不合法");
else {
if(age<20)
System.out.println("未达到");
else
System.out.println("达到");
}
break;
default:
System.out.println("输入性别数据不合法");
break;
循环语句
循环,程序设计语言反复执行某些代码的一种计算机处理过程,是一组相同或相似的语句被有规律地执行
循环三要素
循环变量初始化、
循环条件(以循环变量为判断条件)、
循环变量的改变(向着结束变)
for、while
循环语句可以进行多层嵌套
当循环语句多层嵌套时,break只能跳出本次层循环体,无法用一个break将全部嵌套循环体跳出
for
for循环基本表达式 for(表达式1;表达式2;表达式3)
分号标识着for循环结束
java具有垃圾回收机制,因此在for循环中定义的变量(i),在for结束后也会销毁
for(int i=0;i<100;i++); //分号标识着for循环体结束 ,正确的无编译错误
//i在for中定义,只作用域for
{ System.out.println(i); //编译错误 i未被定义 } //语句块
当for循环为死循环,永远执行不到循环体外的语句
for (int i=0;i<100;i–); //分号标识着for循环体的结束,此for循环没有循环语句块;且死循环
System.out.println(“hello”); //循环体外的一条语句,永远执行不到
for循环特殊表达式
for循环特殊表达式
for(;表达式2;表达式3)
for(;表达式2;)
for(;;)
表达式1和表达式3可使用逗号表达式,多个表达式组成,从左到右计算
//for表达式1和表达式3可使用逗号表达式,多个表达式组成
for(int a=0,b=5;a<b;a++,b--){
System.out.println(a+"-"+b);//0-5、1-4、2-3
}
//结束时a=3,b=2
for(;;)产生1~20的随机数,把随机数的和相加,大于100结束程序
public static void randomTotal(){
int total=0;
int count=0;
Random random=new Random();
//结束循环条件total>=100
//因此输入循环条件为total<100 (放置在表达式2)
for(;total<100;){
count++;
int num=random.nextInt(20)+1; //产生1~20的随机数
total+=num;
}
System.out.println("total:"+total);
System.out.println("count:"+count);
}
while
while 运用于循环次数不定
语句0;循环初始条件 [第一要素]
while(循环条件){ [第二要素]
语句1;循环体 [循环变量改变-第三要素]
}
while 产生1~20的随机数,把随机数的和相加,大于100结束程序
public static void randomTotal(){
Random random=new Random();
int total=0;
int count=0;
while (total<100){
int num=random.nextInt(20)+1;
total+=num;
count++;
}
System.out.println("total:"+total);
System.out.println("count"+count);
}
产生随机数,猜大小
public static void suspectGame(){
Random random=new Random();
Scanner scanner=new Scanner(System.in);
int ranNum= random.nextInt(100)+1;//生成1-1000的数
while (true){
System.out.println("输入一个整数(1-100)");
int guessNum=scanner.nextInt();
while (guessNum<1||guessNum>100){
System.out.println("输入数据不符合规范,请重输:");
guessNum=scanner.nextInt();
}
if(guessNum==ranNum){
System.out.println("恭喜猜对了!随机值为"+ranNum);
break;
}
else if (guessNum>ranNum)
System.out.println("猜大了");
else
System.out.println("猜小了");
}
}
do…while
do { 循环体} while(判断条件);
至少做一次再判断是否需要继续做下一次
随机产生能被3和7整除的整数
public static void randomPrintNum(){
Random random=new Random();
int data;
do {
data=random.nextInt(100)+1;
}while (!(data%3==0&&data%7==0));
//!(data%3==0&&data%7==0) 等价 data%3!=0||data%7!=0
System.out.println("随机产生能被3和7整除的整数为"+data);
}
死循环
一直为true,死循环
int c=0;
while (c>=0) {c++;}
一直为true,死循环
for(int i=5;i<10;i++) {System.out.println(“L”);}
进不去,开始就为false 循环一次不执行(这个不是死循环)
int c1=0;
while (c1>0) {c1++};
编译错误:Unreachable statment 编译时检查到后续的代码没有机会被执行到
若程序为死循环且while使用直接量"true",存在编译错误
由于while条件中用"true"直接量,导致程序在编译时就知道时死循环,检测到后续代码没有机会被执行到
如下所示:
public static void main(String[] args) throws InterruptedException {
while (true){
Date date=new Date();//年月日时分秒
System.out.println(date);
Thread.sleep(1000); //休息1秒输出时间
//抛出异常:throws InterruptedException
}//死循环,无终止条件,一直执行;
int b=9; //这里会报错--编译错误
}
//由于死循环会一直执行,则int b=9这条语句将无法被执行;
//且while条件中使用"true"直接量,会导致程序在编译时就知道时死循环,检测到后续代码没有机会被执行到,则产生编译错误
修改方式: 将直接量赋值给变量 ,从而在编译过程中检查不到,解决编译错误
public static void main(String[] args) throws InterruptedException {
boolean v=true; //定义一个布尔类型变量赋值true
while (v){ //将true变成v变量
Date date=new Date();//年月日时分秒
System.out.println(date);
Thread.sleep(1000); //休息1秒输出时间
//抛出异常:throws InterruptedException
}
int b=9;
}
变量的值在编译过程中不会被访问到,只有在运行中才会剖析,因此可以规避死循环有后续的代码编译报错的情况。
break、continue
break 用于循环或switch…case语句,可使程序终止循环后面的语句,break只能跳出一层循环体(本层循环体)
continue 只用于循环语句中,表示跳过本轮循环体剩余语句,开启下轮循环
1~100不能被5整除的数求和
public static void fiveTotal(){
System.out.println("——————continue————");
int sum=0;
for (int i=1;i<=100;i++){
if(i%5==0)
continue;
//结束本次循环,后续代码不执行,进入到下次循环
sum+=i;
}
System.out.println("sum="+sum); //sum=4000
System.out.println("——————break————");
int sum1=0;
for (int i=1;i<=100;i++){
if(i%5==0)
break;
//结束整个for循环,跳出循环体
sum1+=i;
}
System.out.println("sum1="+sum1); //sum1=10
}
2-100之间的质数
Math.sqrt©
若数c不是素数,则有其他因子、假如为a,b,其中必有一个大于sqrt©,一个小于sqrt©
因此c必有一个小于或等于其平方根的因数
则验证素数时就只需要验证到其平方根就行
即一个合数一定含有小于它平方根的质因子
public static void simpleTest2(){
System.out.print("2-100之间的质数有: ");
for(int i=2;i<=100;i++){
boolean v=true;
for(int j=2;j<=Math.sqrt(i);j++){
if(i%j==0){
v=false;
break;
}
}
if(v)
System.out.print(i+" ");
}
System.out.println();
}
随机生成数组值,冒泡升序排序
冒泡排序,双层for循环
第一个for循环 for(int i=0;i< arr.length-1;i++)
表示arr.length-1 只需要走arr.length-1趟-----即需要进行多少次比较
[若有10个人,则最后一个不用在比较,因此只用10-1=9c次比较即可]
int i=0,因此i< arr.length-1
第二次for循环 for(int j=0;j< arr.length-1-i;j++)
假若有10个元素进行升序排序[即从小到大]
表示每一趟进行的比较,在每一趟的比较中都会找到一个大值放在后面
在后续比较中,通过当前元素arr[j]与ar[rj+1]进行比较大小再确认是否交换位置
从而 当j=8时,代表着数组中第九个元素;它与j+1=9即第十个元素进行比较交换,最后元素则完成一趟比较;
若再继续,j=9;则它需要和j+1=10的arr[10]元素进行交换,会产生数据溢出[因为数组长度为10,没有下标为10的元素]
因此,j< arr.length-1保证了j不会等于最后一个元素,反之报错
[当i=0,进行第一趟比较,会比较出10个中最大的元素,并排置第10个位置[即最后一个位置]
当i=1;进行第二趟比较;这时候只需要从剩下9个元素中比较出最大的元素,并排置第9个位置[即最后二个位置]
…以此类推
]
因此每排一趟,则可以少进行一个元素的比较
因此,j< arr.length-1-i 优化了算法
public static void simpleTest3(){
Scanner scanner=new Scanner(System.in);
Random random=new Random();
System.out.println("数组长度");
int n= scanner.nextInt();
int arr[]=new int[n];
for(int i=0;i<arr.length;i++)
arr[i]= random.nextInt(100)+1; //随机生成数组值
System.out.println("生成的原数组为:"+ Arrays.toString(arr));
for(int i=0;i< arr.length-1;i++) //arr.length-1 只需要走arr.length-1趟
for(int j=0;j< arr.length-1-i;j++){ // 前一个跟后一个比、arr.length-1-i
if(arr[j]>arr[j+1]){ //因此当走到arr.length-2时会与arr.length-1比较
int tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
System.out.println("升序(从小到大)的数组为:"+ Arrays.toString(arr));
}
知识
Double是java定义的类,而double是预定义数据类型(8种中的一种);
两者不同,Double是引用数据类型,double是基本数据类型
Scanner不支持输入char类型
switch…case分支语句中结束循环程序[无法直接使用break]
return 结束方法的运行程序
System.exit(0); 结束整个的程序
方法一:使用一个布尔变量
当需要结束循环时,选择其对应分支,将v变为false;
boolean v=true;
while (v){
System.out.println("选择进行的操作(0-3)");
int n= scanner.nextInt();
switch (n){
case 0:
System.out.println("取款操作成功");
break;
case 1:
System.out.println("存款操作成功");
break;
case 2:
System.out.println("查询操作成功");
break;
case 3:
System.out.println("退出操作成功");
v=false;
break;
default:
System.out.println("输入选项不合法,操作失败");
break;
}
}
方法二:return; 结束方法的运行程序
当需要结束循环时,选择其对应分支,语句放入return; 则结束该mian方法的运行;
后面也不用跟break
当运行到 return; 就不会再继续执行后续,而是直接结束该方法。
while (true){
System.out.println("选择进行的操作(0-3)");
int n= scanner.nextInt();
switch (n){
case 0:
System.out.println("取款操作成功");
break;
case 1:
System.out.println("存款操作成功");
break;
case 2:
System.out.println("查询操作成功");
break;
case 3:
System.out.println("退出操作成功");
return; //结束方法的运行
default:
System.out.println("输入选项不合法,操作失败");
break;
}
}
方法三:System.exit(0); 结束整个的程序
当需要结束循环时,选择其对应分支,语句放入System.exit(0); 则结束该整个程序结束运行;
后面也不用跟break
当运行到 System.exit(0); 就不会再继续执行后续,而是直接结束整个程序
与return;的区别:
return; 结束的是方法
当在某一个方法体里使用return;则会结束该方法(不是mian方法)的运行,当不影响主函数(mian方法)的后续运行;
System.exit(0); 结束的是整个程序
无论将其放在不是mian方法或是主函数(mian方法)里,只要运行到它,则不会再任何操作,直接结束整个程序
while (true){
System.out.println("选择进行的操作(0-3)");
int n= scanner.nextInt();
switch (n){
case 0:
System.out.println("取款操作成功");
break;
case 1:
System.out.println("存款操作成功");
break;
case 2:
System.out.println("查询操作成功");
break;
case 3:
System.out.println("退出操作成功");
System.exit(0); //结束整个的程序
default:
System.out.println("输入选项不合法,操作失败");
break;
}
}
抛出异常:throws
Thread.sleep(1000); //休息1秒输出时间
抛出异常:throws InterruptedException