第一部分 语法基础篇
第1章 概述
1.1 计算机组成部分
计算机系统由硬件和软件组成
硬件:看得见摸得着的物理器件
软件:它是一些列的指令,这些指令主要用于控制硬件来完成一些列特定的工作 (一般软件控制硬件)
常见的硬件:
- CPU:Center Processing Unit 中央处理器 主要指令控制和数值计算功能(日常工作任务)
- 内存:临时性存储数据的存储设备RAM,断电后,数据会消失
- 显卡GPU:Graphic Processing Unit 图形图像处理单元 主要用于计算图形数据(图形图像任务)
- 存储设备:永久性存储设备ROM
- 输入输出设备:键盘、鼠标、显示器等
- 主板:将计算机的其他部件连在一起,形成一个整体
1.2 人机交互方式
主要的人机交互方式:
-
图形化界面操作方式:操作简单,表现直观,容易上手操作,步骤繁琐,占用空间大
-
命令行操作方式 CMD(Command win+R 输入cmd回车)窗口:操作复杂,命令较多,不容易
上手,步骤简单,占用空间小,适合远程操作 -
常用dos命令:
c: 进入C盘根目录
d: 进入D盘根目录
cd xxx 进入xxx目录
dir 查看当前目录下有什么文件和目录
cd / 进入到当前所在盘符的根目录
cd … 返回上一级目录
cls 清屏
exit 退出cmd窗口
1.3 计算机语言
机器语言
根据平台的不同其所表现的形式也不同,为了让计算机能够懂得人类的目的,人类必须以二进制的形式向计算机输入数据。1代表高电平,0代表低电平。
汇编语言
通过一些单词也叫助记符,将一些常用的操作用单词表示,在程序中慢慢出现了人类的语言。比如
计算2+3的结果,在汇编语言里是一下结果。这种代码计算机读不懂,还得将这些助记符包括数据转换
成对应的二进制提交给计算机进行计算。转换的工具,称之为汇编器。汇编语言它的计算方式,还是依赖于计算机的计算方式的。
add 2,3 reslut
汇编语言——>机器语言 (转换)
高级编程语言
从20世纪50年代产生,第一个众所周知的高级编程语言:C语言
之后发展出多种语言C语言->C++语言->Java语言->C#-Python还有PHP等语言。
转换的形式:编译,解释(编译型语言,解释型语言)
- 静态编译语言:C C++ Java
静态:在定义变量的时候有明确的数据类型的区分
编译:将源代码全部进行编译 生成一个可执行的二进制文件 计算机去执行这个二进制文件来运行程序。 - 动态解释语言:Python JS
动态:在定义变量的时候没有明确的数据类型的区分
解释:将源代码从头到尾 读取一行 编译一行 运行一行
1.4 软件与软件开发
软件的定义
软件:一系列按照特定顺序组织的 计算机数据与指令 的 集合
软件的分类
- 系统软件:也称之为是操作系统,主要是用来控制和管理底层硬件的一套指令,操作系统为用
- 户提供最基本的计算机功能。
应用软件:基于系统软件之上的,为用户带了特定领域服务的软件
(需要系统提供基础的服务)
软件开发
大致流程:
- 需求分析
- 编码实现
- 测试编码
- 上线运维
- 更新迭代
- 下线
1.5 Java语言介绍
Java语言的前身Oak(橡树),1994年詹姆斯高斯林和他的团队开发出来的嵌入式编程语言。随着
互联网的发展,紧随潮流编程互联网应用程序开发语言(面向对象),一直到2010年Sun公司被Oracle
收购,Java就属于Oralce的子产品。
Java技术架构
- JavaSE Java Standard Edition Java标准版:桌面型应用程序
- JavaEE Java Enterprise Edition Java企业版:服务器应用程序
- JavaME Java Micro Edition Java微型版:嵌入式应用程序
Oracle公司主要业务:
- 数据库 Oralce数据库 随后也把民间产品MySQL也收购了
- Linux服务器操作系统Solaris(redhat Ubuntu 深度 SUSE)
- 编程语言Java
Microsox公司主要业务:
- SQL Server
- Windows/Windows Server
- C++/C#
Java最大的特点——跨平台
不需要更改软件的内容 一个软件就可以在多个平台上运行。
这归功于JVM:JVM(Java Virtual Machine)Java虚拟机。
Java源代码文件后缀名为xxx.java 所编译出来的二进制文件后缀名为xxx.class JVM主要负责将java语言的字节码文件转换为本地操作系统指令的一个工具软件。所以,最终是字节码文件在跨平台!
1.6 Java开发环境搭建
JRE与JDK
- JRE(Java Runtime Environment)Java运行环境:如果我们的计算机仅仅想运行Java程序的话,装这个软件即可。JRE = JVM + 核心类库。
- JDK(Java Development Kit)Java开发工具包:如果我们的计算机想要去开发一个Java程序的话,装这个软件即可。JDK = 开发工具 + JRE。
- JDK=开发工具+JRE(JVM+核心类库)
jdk安装目录介绍
- bin目录:binary放的都是开发工具
- javac.exe:java编译工具
- java.exe:java运行工具
用法: javac
用法: java [-options] class [args…] (执行类) 或 java [-options] -jar jarfile [args…] (执行 jar 文件)
- db目录:放的是支持数据库开发的一些工具包
- include目录:放的是一些链接底层的一些C头文件代码
- jre目录:jdk自带的运行环境
- lib目录:library 存放的是一些第三方Java库
- javafx-src.zip:javafx图形化界面开发的源码包
- src.zip:Java本身的源代码包
1.8 常见错误
1.语法错误
语法错误:指在编译的过程中出现的一些错误
原因主要产生因素:
- 单词拼写
- 遗漏分号
- 使用中文符号的问题
- 括号不匹配
- 遗漏关键字单词
2.运行错误
运行错误:指编译能够通过,但是在运行期间出现的问题
例如:
public class Sample01 {
public static void main(String[] args) {
System.out.println("Hello World!");
System.out.println(10 / 0); //此处报错 程序中断 后面的代码不执行
System.out.println("Hello World!");
}
}
错误:Exception in thread “main” java.lang.ArithmeticException: / by zero at Sample01.main(Sample01.java:4)
3.逻辑错误
逻辑错误:代码的运行结果和自己认为的结果不一样!
public class Sample01 {
public static void main(String[] args) {
System.out.println(6 / 4 * 3 + 2); //结果是整数 6/4=1
}
}
4.遗漏括号
5.遗漏分号
6.遗漏引号
7.非法使用中文符号
8.单词拼写错误
1.9 编程练习题
- Demo01
public class Demo01 {
public static void main(String[] args) {
System.out.println((9.5 * 4.5 - 2.5 * 3) / (45.5 - 3.5));
}
}
- Demo02
public class Demo02 {
public static void main(String[] args) {
System.out.println(4 * (1 - 1.0 / 3 + 1.0 / 5 - 1.0 / 7 + 1.0 / 9 - 1.0 / 11));
System.out.println(4 * (1 - 1.0 / 3 + 1.0 / 5 - 1.0 / 7 + 1.0 / 9 - 1.0 / 11 + 1.0 / 13));
}
}
- Demo03
public class Demo03 {
public static void main(String[] args) {
System.out.println("周长:" + 2 * 5.5 * Math.PI);
System.out.println("面积:" + 5.5 * 5.5 * Math.PI);
}
}
- Demo04
public class Demo04 {
public static void main(String[] args) {
System.out.println(14 / 1.6 / (45 * 60 + 30) * 3600 + "英里/小时");
}
}
- Demo05
public class Demo05 {
public static void main(String[] args) {
System.out.println(24 * 1.6 / (100 * 60 + 35) * 3600);
}
}
- Demo06
public class Demo06 {
public static void main(String[] args) {
System.out.println("x=" + (44.5 * 0.55 - 50.2 * 5.9) / (3.4 * 0.55 - 50.2 * 2.1));
System.out.println("y=" + (3.4 * 5.9 - 44.5 * 2.1) / (3.4 * 0.55 - 50.2 * 2.1));
}
}
第2章 基本数据与运算
关键字是指被高级编程语言赋予特殊含义的一些单词,关键字一般都是由小写字母组成。
- 用于定义数据类型的关键字:byte short int long float double char boolean void class interface
- 用于定义数据类型值的关键字:true false null
- 用于定义流程控制语句的关键字:if else switch case default while do for break continue return
- 用于定义访问权限修饰符的关键字:public protected private
- 用于定义继承关系的关键字:extends implements
- 用于定义实例对象的关键字:new this super instanceof
- 用于定义函数类型的关键字:static final abstract synchronized
- 用于处理异常的关键字:try catch finally throw throws public class
- 用于包的关键字:package import
- 其他的一些修饰关键字:native assert volatile transient
2.2 标识符
标识符指的是我们在程序中对变量、函数、类、接口、常量所定义的名称,也就是说这些名称是我们自定义的。
标识符必须满足以下组成规则:
- 标识符可以由数字、字母、下划线 _ 、美元符 $ 组成
- 标识符不能以数字开头,当然下划线和美元符其实是可以开头的,但不推荐
- 标识符不能是关键字
- 标识符也不能是Java内置类的名称
- 标识符可以为任意长度,但必须是一个连续的词
- 标识符严格区分大小写
标识符命名的规范:
- 大驼峰式:主要针对类名,接口名。所有单词的首字母大写
- 小驼峰是:主要针对于变量名,函数名。除了第一个单词之外,其他单词首字母大写
- 常量规范:所有单词字母大写,单词与单词之间用下划线分隔
- 包名规范:所有单词字母小写,单词与单词之间用句号 . 分隔
2.3 注释
注释是用于注解和说明程序的一些程序中的内置文本信息的,但这些内置文本不属于代码的范畴。所以在对含有注释的源代码进行编译时,所生成的字节码中不含有注释。注释给人看的!
注释主要有三种:
- 单行注释 //注释内容 直到换行为止
- 多行注释 /* 注释内容 内部可以进行换行 */
- 文档注释 /** 注释内容 内部可以进行换行 */ :文档注释可以被编译器识别,并生成相应的程序说明书。对某一个类进行文档生成时,该类必须是public型
javadoc 类名.java 生成程序说明书
2.4 常量与进制
常量就是指在程序中直接出现的一些数据,也叫字面量
常见的常量:
- 整数常量
- 小数常量
- 字符常量:由一个字母、数字、符号被单引号( ‘’ )标识的数据,两个字节,用的Ascii表示
- 字符串常量:由若干个字母、数字、符号被双引号( “” )标识的数据
- 布尔类型常量
- null常量
public class Sample {
public static void main(String[] args) { //整数常量 System.out.println(10); //十进制整数
System.out.println(0b1001); //二进制整数 打印出来是十进制 System.out.println(0123); //八进制整数
System.out.println(0xAF3); //十六进制整数 //小数常量 System.out.println(3.14);
System.out.println(5.234e3);
System.out.println(1.2e-3); //字符常量
System.out.println('a');
//System.out.println('ab'); ERROR
System.out.println('9');
//System.out.println('12'); ERROR
System.out.println('我');
System.out.println(' ');
//System.out.println(''); ERROR
//System.out.println('''); ERROR
System.out.println('\''); //打印 '
System.out.println('\n'); //打印 换行
System.out.println('\t'); //打印 缩进
//字符串常量
System.out.println("abcd");
System.out.println("a");
System.out.println("");
//字符串空串 ---- null真空
System.out.println("\"");
//布尔常量 System.out.println(true);
System.out.println(false); } }
进制
一个二进制位称之为是一个比特 bit;八个比特称之为一个字节 byte;字节是计算机当中的最小计数单元。
十进制转二进制
- 53 ÷ 2 = 26 ~ 1
- 26 ÷ 2 = 13 ~ 0
- 13 ÷ 2 = 6 ~ 1
- 6 ÷ 2 = 3 ~ 0
- 3 ÷ 2 = 1 ~ 1
- 1 ÷ 2 = 0 ~ 1
余数从下到上 110101 = 1 + 4 + 16 + 32 = 53
二进制转八进制
三位二进制数转化为一为八进制数
二进制转十六进制
四位二进制数转化为一为十六进制数
负数的二进制
- 29的二进制 将正数部分的二进制先取反 再加1 即为负数的二进制
00011101 =>取反 11100010 =>加1 11100011
2.5 变量
变量指变化的量:
- 变量的本质就是在内存中程序所处的进程中的一个临时存储区域
- 该区域的存储值有限制的
- 该区域值的变化必须是同类型的或向下兼容的
- 该区域有其自身的物理内存地址-指针
该区域中 存储值的限制 和 数据的变化类型 由 数据类型 来决定
该区域中 其空间的分配 和 空间的物理内存地址 由计算机底层来决定
2.6 数据类型
在Java当中,数据类型主要分为两大类:基本数据类型、引用数据类型
基本数据类型:在变量的空间中存储数据
- 整型
- byte 1字节
- short 2字节
- int 4字节
- long 8字节
- 浮点型
- float 4字节
- double 8字节
- 字符型
- char 2字节
- 布尔型
- boolean 不确定
在常量中,整型常量默认int类型,小数常量默认是double类型
布尔类型,如果是单一变量的话,在JVM中true被认为是1 false被认为是0 所以是4字节存
如果是布尔类型数组的话,在JVM中true和false被认为是byte类型 1字节
整数类型计算时,如果不存在long类型的话 其他整型的相加结果一律为int
char类型而言 变量空间存的是ASCII编号
给long类型变量赋值时要在常量后加“L”,例:long l1 = 123123123123L;
给float类型变量赋值时要在常量后加“f”,例:float f = 3.14f;
引用数据类型:数据是在堆内存中存储,变量仅仅存放的是数据在堆内存中 的地址
- 字符串
- 数组
- 对象
在Java中,但凡存储在堆内存中的数据,统称为对象
2.7 运算符
1.算术运算符
+ | 加法 | 1+2=3 如果加号左右有字符串 则加号为连接符 |
---|---|---|
- | 加法 | 3-2=1 |
* | 乘法 | 3*2=6 |
/ 除法 | 3/2=1 3.0/2=1.5 | 如果除号两边都是整数 结果为整数;有小数 结果为小数 |
% | 取余 | 9%5=4 注意一点,如果前或后为负数时,余数的符号跟被除数符号相同 |
a++ | 后置自增 | 先调用, 再自身加一 |
++a | 前置自增 | 先自身加一,在调用 |
a– | 后置自减 | 先调用, 再自身减一 |
–a | 前置自减 | 先自身减一,在调用 |
public class Sample {
public static void main(String[] args) {
/*a++
1.先开辟临时存储区 将a的值赋值进去
2.a自身加一
3.临时存储区的值等待被调用 输出 赋值 参与运算
*/
int i = 0; i++;
System.out.println(i++); //1
System.out.println(i); //2 int j = i++;
System.out.println(i); //3
System.out.println(j); //2
i = i++;
System.out.println(i); //3
i = i++; System.out.println(i); //3
int a = 1;
System.out.println(a++ + ++a + a++ + a++ + ++a); // 1 3 3 4 6
}
}
2.赋值运算符
赋值运算符 | 含义 | 备注 |
---|---|---|
+= | 加法赋值 | a+=3 a=a+3 赋值运算符只能用在变量身上 |
-= | 减法赋值 | a-=3 a=a-3 |
类似的还有:
*= ;/=; %=
3.比较运算符
运算的结果为布尔类型
>
大于- < 小于
>
= 大于等于- <= 小于等于
- != 不等于
4.逻辑运算符
- & 单与
- | 单或
- ^ 异或 (相同为假,不同为异)
- ! 非
- && 双与 (当左边为假 则右边不用执行)
- || 双或 ( 当左边为真 则右边不用执行)
5.位运算符
- & 位与
- | 位或
- ^ 位异或
>>
右移- << 左移
>>>
无符号右移 —若被右移的数为正,则高位补0,而若该数为负数,则右移后高位同样补0。- <<< 无符号左移
6.三目运算符
数据类型 变量名 = 布尔表达式?值1:值2;
int number = 10 % 2 == 0? 10 : 2;
补充:变量的交换问题:
int a = 3; int b = 7;
方法一:
int c = a;
a = b;
b = c;
System.out.println(a);
System.out.println(b);
方法二:
a = a + b;
b = a - b;
a = a - b;
System.out.println(a);
System.out.println(b);
方法三:
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println(a);
System.out.println(b);
2.8 常见错误
未声明变量,未初始化变量而使用变量
整型溢出问题
取整错误
- 小数的问题,小数主要去的是近似值 想要得到一个0.5这个值的话 有可能会得到0.4999999
- 整数的问题,1/3 = 0.3333 * 3 = 0.99999 数学上1
超出预期的除法问题
/左右两边是整数,结果为整数,如果/号任意一边出现小数则结果为小数
额外冗余的输入对象
import java.util.Scanner;
public class Sample {
public static void main(String[] args) {
Scanner scanner1 = new Scanner(System.in);
System.out.print("请输入整数:");
int num1 = scanner1.nextInt();
//下面scanner2对象就是一个多余的
Scanner scanner2 = new Scanner(System.in);
System.out.print("请输入小数:");
double num2 = scanner2.nextDouble();
/*Sample.java:3: 错误: 找不到符号 Scanner scanner = new
Scanner(System.in); ^符号: 类 Scanner 位置: 类 Sample */
}
}
第3章 流程控制语句
3.1 if条件语句
单分支if语句
…CodeA
if (布尔表达式) {
语句组;
}
…CodeB
双分支if-else语句
…CodeA
if (布尔表达式) {
语句组A;
} else {
语句组B;
}
…CodeB
多分支if-else-if语句
…CodeA
if (布尔表达式1) {
语句组A;
} else if (布尔表达式2) {
语句组B;
} else if (布尔表达式3) {
语句组C;
} else {
语句组D;
}
…CodeB
3.2 switch分支语句
与if分支语句一样,都是对条件的判断。switch一般用在条件较多的情况下。
一般地,if多分支语句可以和switch分支语句相互转换,但是有一种特殊的情况,if语句可以对区间值或固定值进行判断,switch只能对固定值进行判断。
switch (变量) {
case 值1: //if (变量==值1) {语句组A;}
语句组A;
break;
case 值2:
语句组B;
break;
...
case 值n: //if (变量==值n) {语句组N;}
语句组N;
default: // else {语句组N+1;}
语句组N+1;
break; }
使用switch时需要注意:
- switch所传入的变量可以是char,byte,short,int,String或者枚举类型
- 值1,值2,一直到值n必须是统一数据类型
- 当变量匹配的相关case的值的时候,执行case中的语句,直到遇到break结束;如果该case语句
中没有break,则继续向下执行,直到遇到另外一个break结束
3.3 for循环语句
循环主要解决具有规律性的且具有重复性的代码问题,避免程序冗余
循环四要素
- 1循环的初始化:循环的第1次执行从哪里开始
- 2循环的继续条件:循环从当前轮是否向后执行下一轮
- 3循环体:需要被循环执行的部分
- 4循环的步长、周期:当前循环到下一轮循环之间的变化
for (1循环的初始化;2.循环的继续条件;4.循环的步长) {
3.循环体
}
常见的两大循环问题:
- 已知循环次数的 一般用for语句做
- 未知循环次数但是已知循环结束条件 一般用while语句做
案例:
import java.util.Scanner;
public class Sample {
public static void main(String[] args) {
/*
*****
*/
for (int i = 1; i <= 5; i++) {
System.out.print("*");
}
System.out.println();
System.out.println("=============================");
/*
*****
*****
*****
*****
*/
for (int j = 1; j <= 4; j++) {
for (int i = 1; i <= 5; i++) {
System.out.print("*"); }System.out.println();
}
System.out.println("=============================");
/*
*
**
***
****
*****
******
*******
*/
for (int line = 1; line <= 7; line++) {
for (int i = 1; i <= line; i++) { System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/*
******
*****
****
***
**
*
*/
for (int line = 6; line >= 1; line--) {
for (int i = 1; i <= line; i++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/* i j
* 1 1
** 2 1 2
*** 3 1 2 3
**** 4 1 2 3 4
***** 5 1 2 3 4 5
****** 6 1 2 3 4 5 6 j <= i
***** 7 1 2 3 4 5
**** 8 1 2 3 4
*** 9 1 2 3
** 10 1 2
* 11 1 j <= 12 - i
j <= i && j <= 12 - i
*/
for (int i = 1; i <= 11; i++) {
for (int j = 1; j <= i && j <= 12 - i; j++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/* i |i - 6|
* 1 -5
** 2 -4
*** 3 -3
**** 4 -2
***** 5 -1
****** 6 0
***** 7 1
**** 8 2
*** 9 3
** 10 4
* 11 5
*/
for (int i = 1; i <= 11; i++) {
for (int k = 1; k <= Math.abs(i - 6); k++) {
System.out.print(" ");
}
for (int j = 1; j <= i && j <= 12 - i; j++) {
System.out.print("* ");
}
System.out.println();
}
System.out.println("=============================");
/* j
* 1
* * 1 2
* * 1 2 3
* * 1 2 3 4
* * 1 2 3 4 5
* * 1 2 3 4 5 6
* * 1 2 3 4 5
* * 1 2 3 4
* * 1 2 3
* * 1 2
* 1
*
j == 1 j == i j + i == 12
*/
for (int i = 1; i <= 11; i++) {
for (int k = 1; k <= Math.abs(i - 6); k++) {
System.out.print(" ");
}
for (int j = 1; j <= i && j <= 12 - i; j++) {
if (j == 1 || j == i || j + i == 12) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
3.4 while循环语句
while循环主要用于解决循环次数未知,但循环结束条件已知的情况。
while其实和for循环是可以相互转换的,是因为都逃不开循环四要素
while的语法格式
1.循环的初始化
while (2.循环继续条件) {
3.循环体
4.循环的步长、周期
}
3.5 break、continue跳转语句
break在循环语句中叫做终止语句,终止的是break最近的一层循环
continue在循环语句中叫做跳过语句,跳过本次循环开启下一轮循环
3.6编程练习
Demo18
import java.util.Scanner;
public class Demo18 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//1.提示用户输入一个年份
System.out.print("Enter a year:");
int year = input.nextInt();
//2.判断其是否是闰年 if ((year % 4 == 0 && year % 100 !=0) || (year % 400 == 0)) {
System.out.println(year + "是闰年");
}System.out.println("判断结束!");
}
}
Demo20
import java.util.Scanner;
public class Demo20{
public static void main(String[] args){
//1.提示用户输入a b c三个系数
Scanner input=new Scanner(System.in);
System.out.print("Enter a b c:");
double a=input.nextDouble();
double b=input.nextDouble();
double c=input.nextDouble();
//2.计算delt
double delt=b * b - 4 * a * c;
//3.判断delt,然后执行它有几个解的操作
if(delt>0)
{
double x1=(-b+Math.sqrt(delt))/(2*a);
double x2=(-b-Math.sqrt(delt))/(2*a);
System.out.println("The equation has two roots " + x1 + " and " + x2 );
}
else if(delt==0)
{
double x=(-b+Math.sqrt(delt))/(2*a);
System.out.println("The quation has one root " + x);
}
else{
System.out.println("no root");
}
}
}
Demo23
import java.util.Scanner;
public class Demo23{
public static void main(String[] args)
{
//1.输入一个数
Scanner input = new Scanner(System.in);
System.out.print("Enter a number: ");
int number=input.nextInt();
//2.反转通过取余和乘以10的方法把这个数字反转,一直除到零时结束循环
int temp = number;
int renum=0;
while(temp!=0)
{
renum=renum*10+temp%10;
temp/=10;
}
//3.判断反转的数是否和输入的数相等
if(renum==number)
{
System.out.println(number +" is a palindrome");
}
else{
System.out.println(number + " is not a palindrome");
System.out.println(renum);
}
}
}
Demo24
import java.util.Scanner;
import java.util.Random;
public class Demo24{
/*剪刀(0),石头(1),布(2) usr com 0 1 2 1 0 2 2 0 1 usr == com 平局 usr - com -2 1 用户赢 */
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Random random = new Random();
int com = random.nextInt(3); //[0,3)整数 System.out.print("剪刀(0),石头(1),布(2):");
int usr = input.nextInt();
//判断用户出的是什么
if (usr == 0) {
System.out.print("用户:剪刀 ,");
} else if (usr == 1) {
System.out.print("用户:石头 ,");
} else {
System.out.print("用户:布 ,");
}
//判断电脑出的是什么
if (com == 0) {
System.out.print("电脑:剪刀 ,");
} else if (com == 1) {
System.out.print("电脑:石头 ,");
} else {
System.out.print("电脑:布 ,");
}
//判断用户和电脑谁赢
if (usr == com) {
System.out.println("平局");
} else if (usr - com == -2 || usr - com == 1) {
System.out.println("用户赢");
} else {
System.out.println("电脑赢");
}
}
}
Demo26
import java.util.Scanner;
public class Demo26 {
//数据:点坐标x y 圆心坐标0 0 半径10 点到圆心距离distance
public static void main(String[] args) {
//1.输入点坐标 Scanner input = new Scanner(System.in);
System.out.print("Enter a point:");
double x = input.nextDouble();
double y = input.nextDouble();
double ox = 0; double oy = 0;
double radius = 10;
//2.计算点到圆心的距离
double distance = Math.sqrt(Math.pow(x - ox,2) + Math.pow(y - oy,2));
//3.计算距离与半径的大小关系
if (distance > radius) {
System.out.println("Point ("+ x +"," + y + ") is not in the circle");
}else {
System.out.println("Point ("+ x +"," + y + ") is in the circle");
}
System.out.println("Compute Complete!");
}
}
Demo30
import java.util.Scanner;
public class Demo30{
public static void main(String[] args){
Scanner input =new Scanner(System.in);
//1.输入圆1圆2的中心坐标和半径
System.out.print("请输入圆1圆心 x坐标,y坐标,半径:");
double ox1=input.nextDouble();
double oy1=input.nextDouble();
double radius1=input.nextDouble();
System.out.print("请输入圆2圆心 x坐标,y坐标,半径:");
double ox2=input.nextDouble();
double oy2=input.nextDouble();
double radius2=input.nextDouble();
//2.计算圆心间距离
double distance=Math.sqrt(Math.pow(ox1-ox2,2)+Math.pow(oy1-oy2,2));
//判断圆心距与半径的关系,确定两个圆是相交、相离还是包含(忽略相切)
//distance <= r1 - r2 圆2在圆1内
//distance < r1 + r2 圆2与圆1相交
//distance >= r1 + r2 圆2在圆1外
if (distance <= radius1-radius2)
{
System.out.println("r2在r1内");
}else if( distance <radius1+radius2){
System.out.println("r2与r1相交");
}else{
System.out.println("r2与r1相离");
}
}
}
Demo33
import java.util.Scanner;
public class Demo33{
public static void main(String[] args){
//求最大公约数
Scanner input =new Scanner(System.in);
//1.输入要计算的两个数
System.out.print("请输入两个数: ");
int num1=input.nextInt();
int num2=input.nextInt();
//2.判断哪个数小,最大公约数最大的时候就是与小的那个数相等的时候
int min=num1<num2?num1:num2;
//声明temp,用来暂存最大公约数
int temp=1;
for(int i=min;i>0;i--){
//当它们同时能被一个数整除时,就是最大公约数(循环是从大到小)
if(num1%i==0&&num2%i==0){
temp = i;
break;
}
}
System.out.println("最大公约数为:" + temp);
}
}
Demo35
import java.util.Scanner;
public class Demo35{
public static void main(String[] args)
{
//首先输入一段字符串
Scanner input = new Scanner(System.in);
System.out.print("请输入一段话: ");
String sentence = input.nextLine();
//获取字符串的长度
int length=sentence.length();
boolean flag=true;
//判断第i位是否和倒数第i位字符相同,不同的话就跳出循环且改标志位为false
for(int i = 0; i < length/2; i++){
if(sentence.charAt(i) != sentence.charAt(length-i-1))
{
flag=false;
break;
}
}
//用标志输出它时候回文
if(flag){
System.out.println("它是回文");
}else{
System.out.println("它不是回文");
}
}
}
Demo41
import java.util.Scanner;
public class Demo41{
public static void main(String[] args){
/*
1 0 0
2 1 2 1 0 1 |-1| 0 1
3 2 1 2 3 2 1 0 1 2 |-2| |-1| 0 1 2
*/
Scanner input=new Scanner(System.in);
System.out.print("请输入一个整数: ");
int num=input.nextInt();
for(int i=0;i<=num;i++)
{
//填充图形之前的空格
for(int k=num-i;k>=0;k--){
System.out.print(" ");
}
//假设中间的为0,左边的就是负数取绝对值
for(int j=-(i-1);j<=(i-1);j++)
{
System.out.print(Math.abs(j)+1 + " ");
}
System.out.println();
}
}
}
Demo43
类似41题的思路
import java.util.Scanner;
public class Demo43{
public static void main(String[] args){
//提示并输入一个整数
Scanner input=new Scanner(System.in);
System.out.print("请输入一个整数: ");
int num=input.nextInt();
//循环num次
for(int i=0;i<=num;i++)
{
//在图像前面加空格,排版
for(int k=num-i;k>=0;k--){
System.out.print("\t");
}
//循环(i-1)*2+1次,通过i与这行有多少个数可得
for(int j=-(i-1);j<=(i-1);j++)
{
// System.out.print((int)(Math.pow(2,Math.abs(Math.abs(j)-i+1))) + "\t");
//到中间那个数时j为0,它左边的j是-1,右边的j是1,那么就取绝对值
//中间那个数的是2的i-1次方(这行最大的),旁边依次是他的1/2,那么左右都是是(i-1)-(j的绝对值)
System.out.print((int)(Math.pow(2,i-Math.abs(j)-1)) + "\t");
}
System.out.println();
}
}
}
Demo47
import java.util.*;
public class Demo47{
public static void main(String[] args) {
//输入1个数,用来确定循环次数
Scanner input = new Scanner(System.in);
int max = input.nextInt();
//item初始值为1,第一个加数为1
int item=1;
double e=0;
for (int i= 1; i<=max; i++) {
//分母总是上一个数的分母的i倍 阶乘
item*=i;
e+=1/item;
}
System.out.println(e);
}
}
Demo49
import java.util.*;
public class Demo49{
public static void main(String[] args) {
//定义存储数据的一个数组
String[] arr=new String[]{"剪刀","石头","布"};
Scanner input =new Scanner(System.in);
Random random=new Random();
//用户和电脑各自赢的次数
int comCount=0;
int userCount=0;
while(true){
System.out.print("剪刀(0) 石头(1) 布(2) :");
//用户输入数字,电脑产生随机数
int user=input.nextInt();
int com=random.nextInt(3);
System.out.print("用户: " +arr[user] +",");
System.out.print("电脑: " +arr[com] +",");
//判断用户和电脑的输赢
if (user == com) {
System.out.println("平局");
}else if(user-com==1||user-com==-2){
System.out.println("用户赢");
userCount++;
}else{
System.out.println("电脑赢");
comCount++;
}
//只要有赢两次的就跳出循环
if (userCount==2||comCount==2) {
break;
}
}
//通过赢的次数判断谁取得最终胜利
if (userCount==2) {
System.out.println("最终用户赢");
}else{
System.out.println("最终电脑赢");
}
}
}
Demo50
import java.util.Scanner;
public class Demo50{
public static void main(String[] args) {
//提示并输入一个10进制整数
Scanner input =new Scanner(System.in);
System.out.print("输入一个十进制数:");
int number = input.nextInt();
//暂存求得的余数
String binStr="";
while(number!=0){
//求得的余数放在前,再将之前求得的余数加在后面
binStr=number%2 + binStr;
number/=2;
}
System.out.println("二进制为: " +binStr);
}
}
第4章 常用类
4.1 Math类
Math类是用于数学计算的工具类
在线API
工具类中大部分成员都是静态的(static修饰,可以用类名直接调用)
自带常量
- static double E:自然对数——自然对数的基数
- static double PI:圆周率——圆周长与其直径的比率。
取整方法 - static double ceil(double a):向上取整(数会变大,例如:3.1向上取整是4.0,-3.1向上取整是-3.0)。
- static double floor(double a):向下取整 (数会变小,例如:3.1向下取整是3.0,-3.1向下取整是-4.0) 。
- static long round(double a):四舍五入
三角函数 - static double sin(double a):正弦函数-返回正弦值 参数是弧度值
- static double cos(double a):余弦函数 参数是弧度值
- static double tan(double a):正切函数 参数是弧度值
- static double toDegrees(double a):将弧度转角度 参数是弧度值
- static double toRadians(double angles):将角度转弧度 参数是角度值
- static double asin(double a):反正弦函数 参数是弧度值
- static double acos(double a):反余弦函数 参数是弧度值
- static double atan(double a):反正切函数 参数是弧度值
指数函数
- static double pow(double a, double b):将第一个参数的值返回到第二个参数的幂——求a的b次幂
- static double sqrt(double a):返回的正确舍入正平方根 double值——求a的平方根
- static double cbrt(double a):返回 double值的多维数据集根——求a的立方根
其他方法
- static double abs(double a):求a的绝对值
- static double hypot(double X, double Y):返回sqrt( x 2 + y 2 ),没有中间溢出或下溢。可用于求两点间距离,如:Math.hypot(x1-x2,y1-y2);
- static double max(a,b):返回a和b之间的最大值
- static double min(a,b):返回a和b之间的最小值
- static double random():返回[0,1)之间的随机小数(左闭右开)。
4.2 Scanner类
主要用于负责数据输入的类,底层是和IO流相关。
- String next():获取直到遇到空格为止的一个字符串
- String nextLine():获取直到遇到回车为止的一个字符串
- int nextInt():获取下一个整数 byte short long
- double nextDouble() :获取获取下一个double类型的浮点数
- boolean - nextBoolean() :获取下一个布尔值
- float nextFloat():获取下一个单精度浮点数
4.3 Random类
主要用于产生随机数
- boolean nextBoolean():随机产生布尔类型值[true|false]
- double nextDouble():随机生成0.0~1.0之间的小数
- double nextInt():随机生成一个整数0~232的整数
- double nextInt(n):随机生成一个整数[0,n)的整数
用之前需要new一个Random类的对象,如:Random random=new Random();然后Int i = random.nextInt();
4.4 String类
String是一个类,它描述的是字符串。在Java代码当中,所有字符串常量(字符串字面量)都是String类的一个实例对象。并且,字符串一旦创建,则不可修改 (不可修改其长度,不可修改其内容) 。所以将来对字符串内容的改变,不能在原地改,只能重新创建一个字符串,即改变的不是String类对象的内容,改变的是它的引用,相当于在内存中重新创建了一个常量,然后指向它。
public class Sample {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "ab" + "dc";
//上述代码一共有4个字符串.
//第一个字符串“abc”,第二个“ab”,第三个“dc”,第四个“abdc”,s2最后指向的是“abdc”
}
}
获取字符串相关的信息
- char charAt(int index):获取指定角标index处的字符
- int indexOf(int ch):获取指定字符(编码)在字符串中第一次(从左到右)出现的地方返回的是角标。如果是-1 表示不存在
- int lastIndexOf(int ch):获取指定字符(编码)在字符串中第一次(从右到做)出现的地方返回的是角标
- int indexOf(String str):获取指定字符串在本字符串中第一次(从左到右)出现的地方返回的是角标
- int lastIndexOf(String str):获取指定字符串在本字符串中第一次(从右到左)出现的地方返回的是角标
- int length():获取字符串的长度(字符的个数)
- String[] split(String regex):将字符串按照regex的定义进行切割(regex指的是正则表达式)
- String substring(int beginIndex):截取一段子字符串,从beginIndex开始到结尾
- String substring(int beginIndex, int endIndex):截取一段子字符串,从beginIndex开始到endIndex,左闭右开[a,b)
字符串判断相关
- int compareTo(String anotherString):按照字典顺序比较两个字符串的大小——ASCII码比较,如:“a”.compareTo(“b”); 返回的是a的ASCII码减去b的ASCII码,即-1
- boolean contains(String another):判断当前字符串中是否包含指定字符串another——若包含则返回true,反之
- boolean equals(String another):比较当前字符串与指定字符串的内容是否相同
- boolean isEmpty():判断当前字符串是否为空,等价 length() == 0
- boolean startsWith(String prefix):判断该字符串是否以prefix开头
- boolean endsWith(String suwix):判断该字符串是否已suwix结尾
字符串修改相关
注:字符串一旦创建,则不可修改,这里修改的意思是,根据这个字符串的内容去创建一个新的字符串常量,而这个新的字符串常量是按照一定规则创建的,其内容与先前的字符串内容相关。
- String toLowerCase():将字符串中所有的英文字母全部变为小写
- String toUpperCase():将字符串中所有的英文字母全部变为大写
- String trim():将字符串中两端的多余空格进行删除
- String replace(char oldCh,char newCh):将字符串中oldCh字符替换成newCh字符
不用trim删除字符串中左右两端出现的空格
public class Sample {
public static void main(String[] args) {
String str = " 123123123 12123 "; //去空格后"123123123 12123"
int l = 0;
int r = str.length() - 1;
while (str.charAt(l) == ' ') { //左边向右一直循环到第一个不为空格的字符,然后几下它在第几个,方便之后用substring方法截取。
l++;
}
while (str.charAt(r) == ' ') {
r--; //右侧与左侧同理,不同的是从后往前循环
}
System.out.println("[" + str.substring(l,r + 1) + "]");
}
}
在字符串"abcbcbcbcbcbc"中统计"bcb"出现的次数
贪心算法
public class demo{
public static void main(String[] args){
//最好的算法KMP算法
String s1 = "abcbcbcbcbcbc";
String s2 = "bcb";
//贪心算法 5个
int count = 0;
for (int i = 0; i < s1.length() - s2.length() + 1; i++) { //获取的下标,能比较的最大下标情况是两个字符串末尾重叠处
if (s1.charAt(i) == s2.charAt(0)) {
/*
若下标为i的字符与s2的第0个字符相同,就比较s1中下标为i的s2长
度的子串是否与s2字符串相同,相同则计数加1,否则,继续比较下标i(此时i已加1)的字符是否与s2的第0个字符相同
*/
if (s2.equals(s1.substring(i,i + s2.length()))) {
count++;
}
}
}
System.out.println(count);
}
}
非贪心算法
public class demo{
public static void main(String[] args){
String temp = s1;
int count = 0; //计数
while (true) {
int index = temp.indexOf(s2); //从temp一直到s2子串出现的位置,返回此处下标。
if (index == -1) { //没找到则退出
break;
}
count++; //计算加1
temp = temp.substring(index + s2.length()); //截取新的子串,从找到字符串后面的下标开始,即index+s2.length();
}
System.out.println(count);
}
}
查找两个字符串中最长的公共子串
public class LongestCommonSubstring{
public static void main(String[] args) {
/*
查询两个字符串最长的公共子串
s1 = abcbcbcb
s2 =bcb
最长的子串长度(最长的情况)是短的字符串长度,此处是3
那么就从3开始循环到0,即最长公共子串为3
*/
String s1="今天我喜欢你123";
String s2="123";
String subs = demo.longestCommonSubstring(s1,s2);
System.out.println(subs);
}
public static String longestCommonSubstring(String s1,String s2){
if(s1.length()<s2.length()) //让s1是长的那个字符串
{
String s3=s1;
s1=s2;
s2=s3;
}
for (int i = s2.length();i>0 ; i--){
for (int j = 0;j<=s2.length()-i; j++) { //j是s2的子串的开始下标,最大时是s2末尾倒数第子串长度处
String temp=s2.substring(j,i-j-1);
if(s1.contains(temp)){
return temp; //直接结束该方法
}
}
}
return "";
}
}
4.5 Character类
Character它是char基本数据类型的包装类 ,以下是一些常用方法。
- static boolean isDigit(char ch):判断字符是否是数字
- static boolean isLetter(char ch):判断字符是否是字母
- static boolean isLetterOrDigit(char ch):判断字符是否是数字或字母
- static boolean isLowerCase(char ch):判断是否是小写字母
- static boolean isUpperCase(char ch):判断是否是大写字母
- static boolean isSpaceChar(char ch):判断是否空白字母(空格 制表符 回车)
将十六进制数字转为十进制
import java.util.Scanner;
public class Sample {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入一个十六进制的数字:"); //0~9 A~F
String hex = input.nextLine().toUpperCase();
if (hex.length() == 0) {
System.out.println("没有任何输入!");
return;//程序直接结束
}
for (int i = 0; i < hex.length(); i++) {
char ch = hex.charAt(i);
if (Character.isDigit(ch) || Character.isLetter(ch)) {
if (Character.isLetter(ch) && (ch < 'A' || ch > 'F')) {
System.out.println("非法字符" + ch);
return;
}
} else {
System.out.println("非法字符" + ch);
return;
}
}
int sum = 0;
for (int i = hex.length() - 1; i >= 0; i--) {
char ch = hex.charAt(i);
if (Character.isDigit(ch)) { //'1' ? 1
sum = sum + (int)Math.pow(16 , hex.length() - i - 1) * (ch - 48);
} else { //'A' - 65 + 10 -> 10
sum = sum + (int)Math.pow(16 , hex.length() - i - 1) * (ch - 55);
}
}
System.out.println(sum);
}
}
第5章 方法(函数)
5.1 方法的概念
什么是方法
方法的定义:指一段具有独立功能的代码,作用:减少代码冗余,提高程序的利用率和效率。
如何定义方法
- 需要一个封闭的空间,将这段独立性的代码进行封装,用一对大括号(方法体)
- 需要对每一个封闭的空间进行命名,名称
- 方法所需要的一些原始数据(参数)
- 方法所产生的一些结果数据(返回值)
函数的语法格式
修饰符 方法类型 返回值类型 方法名(数据类型 数据1,数据类型 数据2,...) {
独立功能的代码片段;
return 函数的计算结果;
}
- 修饰符:指的是方法的访问权限,public private default(默认) protected
- 方法类型:函数的分类,本地方法native,静态方法static,同步方法synchronized
- 返回值类型:指的就是方法计算结果的数据类型 如果方法没有返回值 则为void
- 方法名:方法的名称,用于定义和调用方法
- 参数列表:指的是外界向方法传入的数据(实际参数),由这些参数变量进行接收(形式参数)
- 方法体:具有独立功能的代码片段;
return:仅仅表示方法结束!如果方法有返回值,则return后跟返回值;如果没有返回值,则return可以不写,但是是存在的(隐藏的 在最后一行)
根据形参和返回值来看,函数有如下几个分类 - 有参数有返回值
- 有参数没返回值
- 没参数有返回值
- 没参数没返回值
总结定义方法时需要考虑的有哪些?
方法的运行有哪些未知的参数?(需要的参数值)
方法的运行结果有是什么?
明确参数和结果
明确内容和返回
方法到底要干什么?尽量将独立功能且重复性较高的代码片段提取出来(减少代码冗余)
5.2 方法的运行原理
方法的运行是基于栈运行的
栈:是一种先进后出的容器,我们这里面所说的栈是指JVM中的栈内存空间
每一个函数,叫做栈帧,栈帧中所包含的内容有函数的定义,参数列表,函数的执行内容代码
每一个方法要运行,就相当于这个栈帧进入到栈内存中-入栈
如果一个方法即将结束,将这个栈帧从栈顶移出-出栈
如果栈内存中有多个栈帧,运行的是最上面的栈帧,底下的栈帧暂停运行,直到该栈帧为栈顶元素
比如:主方法先进栈,开始逐行运行,如果执行到第n行,调用另外一个方法A,则主方法在第n行
暂停运行,将另一个方法A的栈帧入栈,再继续逐行运行,直到方法A的内容执行完毕,函数A出栈,主
方法接着从第n行继续向下执行。以此类推。
5.3 方法重载
同一个类中可以出现多个同名方法,这个现象就叫做函数的重载(overload)
如何来区分同名函数是否是重载关系呢?前提必须是同名,和返回值类型无关(返回值类型只和函数的计算功能相关),和权限也没有关系,和形式参数的名称也无关!只和形式参数的数据类型有关(类型、数量、次序)
下列哪些是该方法的重载:
public static void show(int a ,float b ,char c){}
- int show(int x, float y, char z) :不算重载 数据类型都是int float char
- void show(float b,int a,char c):算重载,顺序不一样float int char
- void show(int a,int b,int c):算重载,顺序不一样int int int
- double show():算重载,参数不一样
寻找重载方法的流程:
-
- 看是否有确切的参数定义匹配,int int 找 int int
-
- 看是否有可兼容的参数定义匹配,int int找double double或int double或double int
-
- 如果可兼容的参数定义匹配较多,会报引用确定报错 引用不明确
5.4 方法的递归
方法的递归就是指方法自身调用自身。
- 但凡迭代能够解决的问题,递归都可以解决;递归能够解决的问题,迭代就不一定了
- 相对而言,从内存的角度而言,方法如果过多的自我调用,势必会对内存不友好,占用过多
- 通常来讲,同样的问题用递归写要比用迭代写代码量较少
写递归时,一定要确定递归结束条件-递归边界
递归实现斐波那契数列
public class Sample {
public static void main(String[] args) {
/*1 1 2 3 5 8 13 21 34 55 ... 1 x=1,x=2
f(x) =
f(x-1) + f(x-2) x>2
f(5)
f(4) f(3)
f(3) f(2) f(2) f(1)
f(2) f(1) */
//递归O(2^n)
System.out.println(f(35));
//迭代O(n)
System.out.println(fibo_it(35));
}
public static int fibo_it(int x) {
if (x == 1 || x == 2) {
return 1;
}
/
*1 1 2 3
c
a b
*/
int a = 1;
int b = 1;
int c = 0;
for (int i = 3; i <= x; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
public static int f(int x) {
if (x == 1 || x == 2) {
return 1;
}else {
return f(x-1) + f(x-2);
}
}
}
5.5 编程练习题
汉诺塔
public class Demo81 {
/*
前4个 x->z
前3个 x->y
前2个 x->z
前1个 x->y
第2个 x->z
前1个 y->z
第3个 x->y
前2个 z->y
前1个 z->x
第2个 z->y
前1个 x->y
第4个 x->z
前3个 y->z
前2个 y->x
前1个 y->z
第2个 y->x
前1个 z->x
第3个 y->z
前2个 x->z
前1个 x->y
第2个 x->z
前1个 y->z
*/
public static void main(String[] args) {
String x = "x";
String y = "y";
String z = "z";
hano(3,x,y,z);
//前3层从 x->z
//前2层从 x->y
}
public static void hano(int level,String begin,String mid,String end) {
if (level == 1) {
System.out.println(begin+"->"+end);
} else {
//前level-1层
hano(level - 1,begin,end,mid);
System.out.println(begin+"->"+end);
//前leve1-1层
hano(level - 1,mid,begin,end);
}
}
}
第6章 数组
6.1 数组的概念及定义
数组主要用于解决大量数据计算与存储的问题
数组是Java提供的一种最简单的数据结构,可以用来存储一个元素 个数固定 且 类型相同 的有序集。
数组在内存中的情况
栈:主要用于运行函数的内存
堆:主要用于存储数据对象的内存
每一个数组而言,都是存在堆内存当中,每一个数组都是一个对象
数组本质上就是在堆内存中一系列地址连续且空间大小相等的存储空间(变量),每一个存储空间用来存储数据(基本,引用)
数组是在堆内存中存储,称之为是一个对数对象,并且在堆内存中存储的数据都有 默认初始化的流程。所以数组创建之初,每一个存储空间里面都会被JVM初始化该数据类型对应的零值。
数组的地址是连续的,所以通过公式:An=A1+(n-1)*d可以快速访问到其他的元素,所以对于
数组而言查找元素比较快的。将元素的真实物理地址转换成对应的角标获取元素。
调用数组是通过一个变量存储该数组在堆内存当中的首元素的地址。
当数组一旦定义出来,其长度不可变,存储空间的内容是可变的
所以我们在定义数组的时候,要么把长度固定,要么直接输入相关的元素。(两种方式)
数组的定义方式
//创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值
数据类型[] 数组名 = new 数据类型[长度];
//创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤的!
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,…,数据n};
数据类型[] 数组名 = {数据1,数据2,…,数据n};
6.2 常用数组操作
1.数组遍历问题
- 通过角标遍历 可以在遍历的过程中对指定的元素进行修改
- foreach遍历 主要针对的是一些可迭代对象 Iterable,但是这种遍历方式 只能获取元素,不能修改元素
2.数组最值问题
求数组中的最大最小值
3.数组扩容问题
public class Sample {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
arr = add(arr,6);
arr = add(arr,6);
arr = add(arr,6);
arr = add(arr,6);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
//在指定的数组arr中添加元素element
public static int[] add(int[] arr, int element) {
int[] newArr = new int[arr.length + 1];
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
newArr[newArr.length - 1] = element;
return newArr;
}
}
创建一个新数组住,然后把原来的数组放进去,再进行相应的扩容
4.选择排序算法
步骤:
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 重复第二步,直到所有元素均排序完毕。
代码:
public class SelectionSort{
public static void main(String[] args) {
int[] arr = {1,3,5,4,2};
sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void sort(int[] sourseArr){
for (int i = 0; i < sourseArr.length - 1; i++) {
int min = sourseArr[i];
for (int j = i+1; j < sourseArr.length; j++) {
if (sourseArr[j] < min) {
swep(sourseArr,i,j);
}
}
}
}
public static void swep(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
5.冒泡排序算法
步骤:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
图片来源:菜鸟教程
代码:
public class BubbleSort{
public static void main(String[] args) {
int[] arr = {1,3,5,4,2};
bubbleSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void bubbleSort(int[] sourseArr){
for (int i = 0; i < sourseArr.length - 1; i++) {
for (int j = 0; j < sourseArr.length - 1 - i; j++) {
if(sourseArr[j] > sourseArr[j + 1]){
swep(sourseArr, j, j + 1);
}
}
}
}
public static void swep(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
6.插入排序算法
步骤:将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
图片来源:菜鸟教程
代码:
public class InsertSort{
public static void main(String[] args) {
int[] arr = {1,3,5,4,2};
insertSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void insertSort(int[] sourseArr){
for(int i = 1; i < sourseArr.length; i++){
int e = sourseArr[i];
int j = 0;
for(j = i; j > 0 && sourseArr[j-1] > e; j--){
sourseArr[j] = sourseArr[j-1];
}
sourseArr[j] = e;
}
}
}
7.计数排序算法
步骤:
- 找出待排序的数组中最大和最小的元素值(max,min)
- 统计数组中每个值为number的元素出现的次数,存入数组temp的第number-min项(统计出现次数)
- 反向填充目标数组:遍历temp数组,将第index项的加min依次填回原来的数组,同时index项的值减1
图片来源:菜鸟教程
代码:
public class CountingSort{
public static void main(String[] args) {
int[] arr = new int[]{1,-5,-6,0,6,8,10,-1,-1,-5,0,0,6};
countingSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] +" ");
}
}
public static void countingSort(int[] arr){
//求数组中的最大值和最小值,以确定临时数组的长度
int min = arr[0];
int max = arr[0];
for(int i=0; i < arr.length; i++){
if ( arr[i] > max){
max = arr[i];
}
if ( arr[i] < min){
min = arr[i];
}
}
//关系:number = 数组中最小值min + 临时数组下标index
//定义一个存数字出现次数的数组
int[] temp = new int[max - min +1];
//遍历所求数组,统计数字出现次数并存放在temp数组中
for(int i = 0; i < arr.length; i++){
int index = arr[i] - min;
temp[index]++;
}
//将数放回原来的数组
int k = 0;
for (int i = 0; i < temp.length; i++) {
while(temp[i] > 0){
arr[k] = i + min;
k++;
temp[i]--;
}
}
}
}
8.基数排序算法
思路:
首先按数组中值的个位放入对应(0-9号桶)的桶中,后按桶的顺序(0-9号桶)将存入桶中的值依次去取出(先进先出)到原数组中,然后十位、百位也是如此。
步骤:
- 1.先找到最大值 决定轮数
- 2.创建十个桶
- 3.进行数字分类(存入桶)和规整(从桶中取出到数组)
代码:
import java.util.LinkedList;
public class RadixSort{
//基数排序
public static void main(String[] args) {
int[] arr = new int[]{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
radixSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] +" ");
}
}
public static void radixSort(int[] arr){
//1.先找到最大值 决定轮数
int max = arr[0];
for(int i = 0; i < arr.length; i++){
if(arr[i] > max){
max = arr[i];
}
}
//轮数
int radex = String.valueOf(max).length();
//2..创建十个桶 每一个桶是LinkedList
LinkedList<Integer>[] queues = new LinkedList[10];
for(int i = 0; i < queues.length; i++){
queues[i] = new LinkedList<Integer>();
}
//3.进行数字分类和规整
//r=0个位 r=1十位 r=2百位...
for (int r = 0; r < radex; r++) {
//先按照r进行分类
for(int i = 0; i < arr.length; i++){ //遍历数组
int index = getIndex(arr[i],r); //获得第i项该装哪一个桶的下标
queues[index].offer(arr[i]);
}
//重新规整到arr里
int k = 0;
for (int index = 0; index < queues.length ; index++) {
while(!queues[index].isEmpty()){
arr[k++] = queues[index].poll();
}
}
}
}
public static int getIndex(int num,int r){
int index = 0;
for(int i = 0; i <= r; i++){
index = num % 10;
num /= 10;
}
return index;
}
}
9.二分查找算法
有一个前提,所查找的数据集必须是有序的(升序,降序)
public class Sample {
//二分查找
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
int min = 0;
int max = arr.length - 1;
int mid = (min + max) / 2;
int key = 10;
while (arr[mid] != key) {
if (key < arr[mid]) {
max = mid - 1;
}
if (arr[mid] < key) {
min = mid + 1;
}
if (min > max) {
mid = -1; break;
}
mid = (min + max) / 2;
}
System.out.println(mid);
}
}
10.可变长参数列表
6.3 二维数组
二维数组本质上是一个一维数组,只不过该一维数组里面的元素是另一个一维数组。
也就是一个数值中的每一项都存着一个其他数组的首地址。
//数据类型[][] 矩阵名 = new 数据类型[row][col];
/*数据类型[][] 矩阵名 = new 数据类型[][] { {...}, {...}, {...} };
数据类型[][] 矩阵名 = { {...}, {...}, {...} };*/
import java.util.Scanner;
public class ShortDistance{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
double[][] points = new double[8][2];
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < points[i].length; j++) {
System.out.print("请输入" + i + 1 + "点坐标 x y : ");
points[i][0] = input.nextDouble();
points[i][1] = input.nextDouble();
}
}
double shortDistance = getShortDistance(points,0,1);
int p1 = 0;
int p2 = 1;
for (int i = 0; i < points.length - 1; i++){
for (int j = i; j < points.length; j++){
double distance = getShortDistance(points,i,j);
if (shortDistance > distance) {
shortDistance = distance;
p1 = i;
p2 = j;
}
}
}
System.out.printf("(%.1f,%.1f)和(%.1f,%.1f)的距离最短,最短距离为:%.1f",points[p1][0],points[p1][1],points[p2][0],points[p2][1],shortDistance);
}
public static double getShortDistance(double[][] points,int p1,int p2){
return Math.hypot(points[p1][0] - points[p2][0],points[p1][1] - points[p2][1]);
}
}
6.4 练习
Demo82
public class Demo82{
public static void main(String[] args) {
//输入数字1~100
int[] arr = new int[101];
//0 1~100
Scanner input = new Scanner(System.in);
System.out.print("Enter numbers:");
while (true) { int num = input.nextInt();
if (num == 0) { break; }arr[num]++;
}
for (int i = 1; i < arr.length; i++) {
if (arr[i] != 0) {
if (arr[i] == 1) {
System.out.println(i + " occurs " + arr[i] + " time");
} else {
System.out.println(i + " occurs " + arr[i] + " times");
}
}
}
}
}
Demo83
import java.util.*;
public class Demo83 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter 10 numbes:");
/*思路1:动态扩容数组*/
/*int[] arr = new int[0];
for (int i = 0; i < 10; i++) {
int num = input.nextInt();
if (!contains(arr,num)) {
arr = add(arr,num);
}
}
System.out.println(Arrays.toString(arr));
*/
/*思路2:固定数组长度 用标记表示有效数据 */
int[] arr = new int[10]; int size = 0; //表示有效数据的个数 和新元素进入的角标
for (int i = 0; i < 10; i++) {
int num = input.nextInt();
if (!contains(arr,num,size)) {
arr[size++] = num;
}
}
System.out.println(toString(arr,size));
}
public static String toString(int[] arr,int size) {
if (size == 0) {
return "[]"; }String s = "[";
for (int i = 0; i < size; i++) {
if (i == size - 1) {
s += arr[i] + "]";
} else {
s += arr[i] + ", ";
}
}
return s;
}
public static boolean contains(int[] arr, int num,int size) {
for (int i = 0; i < size; i++) {
if (arr[i] == num) { return true;
}
}
return false;
}
public static int[] add(int[] arr, int num) {
int[] newArr = new int[arr.length + 1];
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i]; }newArr[newArr.length - 1] = num;
return newArr;
}
public static boolean contains(int[] arr, int num) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == num) {
return true;
}
}
return false;
}
}
Demo85
public class Demo85 {
public static void main(String[] args) {
System.out.println(gcd(35,40,55,30,25));
System.out.println(gcd(28,16));
}
public static int gcd(int ... numbers) {
int min = getMin(numbers);
for (int i = min; i >= 1; i--) {
boolean flag = true;
for (int j = 0; j < numbers.length; j++) {
if (numbers[j] % i != 0) {
flag = false;
break;
}
}
if (flag) {
return i;
}
}
return 1;
}
public static int getMin(int[] numbers) {
int min = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] < min) { min = numbers[i];
}
}
return min;
}
}
Demo88
import java.util.*;
public class Demo88 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Random random = new Random();
System.out.print("请输入球的个数:");
int balls = input.nextInt();
System.out.print("请输入槽子的个数:");
int slots = input.nextInt();
int[] temp = new int[slots];
//槽子的数组 //路径的个数 String[] paths = new String[balls];
for (int i = 0; i < paths.length; i++) {
String path = "";
int rCount = 0; //拼接每一个路径
for (int j = 0; j < slots - 1; j++) {
if (random.nextInt(2) == 0) {
path += "L";
} else {
path += "R";
rCount++;
}
}
paths[i] = path;
System.out.println(path);
temp[rCount]++;
}
System.out.println(Arrays.toString(temp));
}
}
有一个r就加1
Demo90
import java.util.*;
public class Demo90 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入数字的个数:");
int len = input.nextInt();
int[] arr = new int[len];
System.out.print("请输入数字:");
for (int i = 0; i < arr.length; i++) {
arr[i] = input.nextInt();
}
for (int i = 0; i < arr.length - 3;) {
int count = 1; int j = 0;
for ( j = i + 1; j < arr.length; j++) {
if (arr[j] == arr[i]) { count++;
} else {
break;
}
}
if (count >= 4) {
System.out.println("有!");
return;
} else {
i = j;
}
}
System.out.println("没有!");
}
}
Demo91
import java.util.*;
public class Demo91 {
public static void main(String[] args) {
int[] arr1 = {1,3,5,7,9};
int[] arr2 = {2,4,6,8,10};
int[] arr3 = merge(arr1,arr2);
System.out.println(Arrays.toString(arr3));
}
public static int[] merge(int[] arr1,int[] arr2) {
int[] arr3 = new int[arr1.length + arr2.length];
int p1 = 0;
int p2 = 0;
int p3 = 0;
while (p1 < arr1.length || p2 < arr2.length) {
if (p1 < arr1.length && p2 >= arr2.length) {
arr3[p3++] = arr1[p1++];
} else if (p1 >= arr1.length && p2 < arr2.length) {
arr3[p3++] = arr2[p2++];
} else if (arr1[p1] < arr2[p2]) {
arr3[p3++] = arr1[p1++];
} else {
arr3[p3++] = arr2[p2++];
}
}
return arr3;
}
}
Demo92
import java.util.*;
public class Demo92 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Random random = new Random();
String[] words = {"banana","orange","python","apple","computer"};
while (true) {
//1.随机抽取一个单词
String word = words[random.nextInt(words.length)];
//2.创建该单词的状态数组
boolean[] statues = new boolean[word.length()];
int missed = 0; //错误的次数
//开始下一个字母的输入
while (!isOver(statues)) {
//3.按照状态数组获取提示的密文
String password = getPassword(word,statues);
//4.提示用户输入一个字母
System.out.print("Enter a letter " + password + ":" );
String letter = input.nextLine();
//5.判断这个字母是否出现在字符串中
if (word.contains(letter)) {
//6.改变字母的状态
if (!changeStatues(word,letter,statues)) {
System.out.println("\t" + letter + " is alreay in the word");
}
} else {
System.out.println("\t" + letter + " is not in the word");
missed++;
}
}
System.out.println("The word is " + word + ". You missed " + missed);
System.out.print("Do you again?(y/n)");
String choice = input.nextLine();
if (choice.equals("n")) {
break;
}
}
}
public static boolean changeStatues(String word,String letter,boolean[] statues) {
//"a" -> 'a'
char ch = letter.charAt(0);
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == ch) {
if (statues[i]) { //如果字符所在的角标i对应的状态已经是true 表示此次没有改变成功-重复输入的字符
return false;
} else {
statues[i] = true;
}
}
}
return true;
}
public static boolean isOver(boolean[] statues) {
for (int i = 0; i < statues.length; i++) {
if (!statues[i]) {
return false;
}
}
return true;
}
public static String getPassword(String word,boolean[] statues) {
String password = "";
for (int i = 0; i < statues.length; i++) {
if (statues[i]) {
password += word.charAt(i);
} else {
password += "*";
}
}
return password;
}
}
Demo101
五子棋
import java.util.Scanner;
public class Demo101 {
//1.创建一个棋盘
public static String[][] board = new String[15][15];
//玩家轮流计数
public static int player = 0;
//黑棋和白棋
public static String BLACK_CHESS = "O";
public static String WHITE_CHESS = "X";
public static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
//2.给棋盘的每一个元素要赋值+
initBoard();
printBoard();
//3.开始下棋
startGame();
}
public static void startGame() {
while (!isGameOver()) {
if (player % 2 == 0) {
//黑方下棋
System.out.println(">>>请黑方下棋");
playChess(BLACK_CHESS);
} else {
//白方下棋
System.out.println(">>>请白方下棋");
playChess(WHITE_CHESS);
}
player++;
}
if (player == 15 * 15) {
System.out.println(">>>和棋,游戏结束!");
} else {
if ((player - 1) % 2 == 0) {
System.out.println(">>>黑胜!游戏结束!");
} else {
System.out.println(">>>白胜!游戏结束!");
}
}
}
public static boolean isGameOver() {
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
if (!board[row][col].equals("+")) {
//向右
if (col < 11) {
boolean flag = true;
for (int c = col + 1; c <= col + 4; c++) {
if (!board[row][col].equals(board[row][c])) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
//向下
if (row < 11) {
boolean flag = true;
for (int r = row + 1; r <= row + 4; r++) {
if (!board[row][col].equals(board[r][col])) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
//向右上
if (row > 3 && col < 11) {
boolean flag = true;
for (int r = row - 1 , c = col + 1; c <= col + 4; r-- , c++) {
if (!board[row][col].equals(board[r][c])) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
//向右下
if (row < 11 && col < 11) {
boolean flag = true;
for (int r = row + 1 , c = col + 1; c <= col + 4; r++ , c++) {
if (!board[row][col].equals(board[r][c])) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
}
}
}
if (player == 15 *15) {
return true;
}
return false;
}
public static void playChess(String chess) {
System.out.print(">>>请输入棋子坐标:");
int x = input.nextInt() - 1;
int y = input.nextInt() - 1;
if (!board[x][y].equals("+")) {
System.out.println(">>>此处已有棋子,请重新下棋!");
player--;
return;
}
board[x][y] = chess;
printBoard();
}
public static void printBoard() {
System.out.print(" ");
for (int i = 1; i <= board[0].length; i++) {
System.out.printf("%-2d",i);
}
System.out.println();
for (int i = 0; i < board.length; i++) {
System.out.printf("%2d ",i + 1);
for (int j = 0; j < board[i].length; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
public static void initBoard() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
board[i][j] = "+";
}
}
}
}