javase第三轮笔记总结

 

5章 函数

5.1 函数的概念

什么是函数

  函数的定义就是指一段具有独立功能的代码,减少代码冗余,提高程序的利用率和效率。
  我们应该如何去定义函数呢?
 
  1. 需要一个封闭的空间,将这段独立性的代码进行封装,用一对大括号
  2. 需要对每一个封闭的空间进行命名,函数名
  3. 函数所需要的一些原始数据
  4. 函数所产生的一些结果数据

函数的语法格式

修饰符 函数类型 返回值类型 函数名(数据类型 数据1,数据类型 数据2,...) {
    独立功能的代码片段;
    return 函数的计算结果;
}
  1. 修饰符:指的是函数的访问权限,public private 默认 protected
  2. 函数类型:函数的分类,本地函数native,静态函数static,同步函数 synchronized
  3. 返回值类型:指的就是函数计算结果的数据类型 如果函数没有返回值 则为void
  4. 函数名:就是函数的名称
  5. 参数列表:指的是外界向函数传入的数据(实际参数),由这些参数变量进行接收(形式参数)
  6. 函数体:具有独立功能的代码片段;
  7. return:仅仅表示函数结束!如果函数有返回值,则return后跟返回值;如果没有返回值,则return可以不写,但是是存在的(隐藏的 在最后一行)

根据形参和返回值来看,函数有如下几个分类

有参数有返回值

例:求三个数字当中的最大值

public class Sample {
        public static void main ( String [] args ) {
             int max = getMax ( 1 , 2 , 3 );
             System . out . println ( max );
}
public static int getMax ( int a , int b , int c ) {
/*
if (a >= b && a >= c) {
        return a;
}else if (b >= a && b >= c) {
        return b;
}else {
       return c;
}
*/
if ( a >= b && a >= c ) {
      return a ;
}
if ( b >= a && b >= c ) {
     return b ;
}
if ( c >= a && c >= b ) {
     return c ;
}
    return - 10000 ;
}
}

 

有参数没返回值

例:将三个字符串的反转,并拼接打印

 

public class Sample {
      public static void main ( String [] args ) {
                print ( "123" , "456" , "789" );
}
//123 456 789 =? 321654987
public static void print ( String s1 , String s2 , String s3 ) {
       System . out . println ( reverse ( s1 ) + reverse ( s2 ) + reverse ( s3 ));
}
public static String reverse ( String s ) {
       String res = "" ;
       for ( int i = s . length () - 1 ; i >= 0 ; i -- ) {
                res += s . charAt ( i );
}
       return res ;
}
}

 

没参数有返回值
例: 获取当前时间的字符串
 
public class Sample {
public static void main ( String [] args ) {
String currentTime = getTime ();
System . out . println ( currentTime );
}
public static String getTime () {
//1. 获取总毫秒数
long millis = System . currentTimeMillis ();
//2. 计算总秒数
long seconds = millis / 1000 ;
//3. 计算总分钟数
long minutes = seconds / 60 ;
//4. 计算总小时数
long hours = minutes / 60 ;
//5. 计算当前小时数
long currentHours = hours % 24 ;
//6. 计算当前分钟数
long currenrMinutes = minutes % 60 ; 没参数没返回值
 
//7. 计算当前秒数
long currentSeconds = seconds % 60 ;
return currentHours + ":" + currenrMinutes + ":" + currentSeconds ;
}
}

 

没参数有返回值
例:
public class Sample {
public static void main ( String [] args ) {
getTime ();
}
public static void getTime () {
//1. 获取总毫秒数
long millis = System . currentTimeMillis ();
//2. 计算总秒数
long seconds = millis / 1000 ;
//3. 计算总分钟数
long minutes = seconds / 60 ;
//4. 计算总小时数
long hours = minutes / 60 ;
//5. 计算当前小时数
long currentHours = hours % 24 ;
//6. 计算当前分钟数
long currenrMinutes = minutes % 60 ;
//7. 计算当前秒数
long currentSeconds = seconds % 60 ;
System . out . println ( currentHours + ":" + currenrMinutes + ":" +
currentSeconds );
}
}

 

总结定义函数时需要考虑的有哪些?

  1. 函数的运行有哪些未知的参数?
  2. 函数的运行结果有是什么?
  3. 明确参数和结果
  4. 明确内容和返回
  5. 函数到底要干什么?尽量将独立功能且重复性较高的代码片段提取出来

 

 

5.2 函数的运行原理

函数的运行是基于栈运行的

栈:是一种先进后出的容器,我们这里面所说的栈是指 JVM 中的栈内存空间
每一个函数,叫做栈帧,栈帧中所包含的内容有函数的定义,参数列表,函数的执行内容代码
每一个函数要运行,就相当于这个栈帧进入到栈内存中 - 入栈
如果一个函数即将结束,将这个栈帧从栈顶移出 - 出栈
如果栈内存中有多个栈帧,运行的是最上面的栈帧,底下的栈帧暂停运行,直到该栈帧为栈顶元素
比如:主函数先进栈,开始逐行运行,如果执行到第 n 行,调用另外一个函数 A ,则主函数在第 n
暂停运行,将另一个函数 A 的栈帧入栈,再继续逐行运行,直到函数 A 的内容执行完毕,函数 A 出栈,主
函数接着从第 n 行继续向下执行。以此类推。
 

5.3 函数重载

同一个类中可以出现多个同名函数,这个现象就叫做函数的重载( overload
 
如何来区分同名函数是否是重载关系呢?前提必须是同名,和返回值类型无关(返回值类型只和函
数的计算功能相关),和权限也没有关系,和形式参数的名称也无关!只和形式参数的数据类型有关
(数量,排列组合)
 
下列哪些是该函数的重载:
  1. int show(int x, float y, char z) :不算重载 数据类型都是int float char
  2. void show(float b,int a,char c):算重载,顺序不一样float int char
  3. void show(int a,int b,int c):算重载,顺序不一样int int int
  4. double show():算重载,参数不一样
  寻找重载函数的流程:
 
1. 看是否有确切的参数定义匹配, int int int int
2. 看是否有可兼容的参数定义匹配, int int double double int double double int
3. 如果可兼容的参数定义匹配较多,会报引用确定报错 引用不明确
 

5.4 函数的递归

函数的递归就是指函数自身调用自身。
 
递归的特点
  1. 但凡迭代能够解决的问题,递归都可以解决;递归能够解决的问题,迭代就不一定了
  2. 相对而言,从内存的角度而言,函数如果过多的自我调用,势必会对内存不友好,占用过多
  3. 通常来讲,同样的问题用递归写要比用迭代写代码量较少

 

用递归实现斐波那契数列

 

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 );
}
}
}
 

用递归实现汉诺塔

 

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 数组的概念及定义

数组主要用于解决大量数据计算与存储的问题
比如:输入 100 个数字,统计其中的最大值和最小值并计算平均值,创建 100 个变量,会有一堆 if-
else 语句,比较麻烦。
数组是 Java 提供的一种最简单的数据结构,可以用来存储一个元素 个数固定 类型相同 的有序
集。
数组在内存中的情况
栈:主要用于运行函数的内存
堆:主要用于存储数据对象的内存
每一个数组而言,都是存在堆内存当中,每一个数组都是一个对象
数组本质上就是在堆内存中一系列地址连续且空间大小相等的存储空间(变量),每一个存
储空间用来存储数据(基本,引用)
数组是在堆内存中存储,称之为是一个对数对象,并且在堆内存中存储的数据都有 默认初始
的流程。所以数组创建之初,每一个存储空间里面都会被 JVM 初始化该数据类型对应的零值。
数组的地址是连续的,所以通过公式: An=A1+(n-1)*d 可以快速访问到其他的元素,所以对于
数组而言查找元素比较快的。将元素的真实物理地址转换成对应的角标获取元素。
如何来调用数组呢?通过一个变量存储该数组在堆内存当中的首元素的地址。
当数组一旦定义出来,其长度不可变,存储空间的内容是可变的
所以我们在定义数组的时候,要么把长度固定,要么直接输入相关的元素。
 
数组的定义方式
// 创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值
数据类型 [] 数组名 = new 数据类型 [ 长度 ];
// 创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤的!
数据类型 [] 数组名 = new 数据类型 []{ 数据 1 , 数据 2 ,..., 数据 n };
数据类型 [] 数组名 = { 数据 1 , 数据 2 ,..., 数据 n };

 

 

public class Sample {
public static void main ( String [] args ) {
int [] arr = new int [ 5 ];
System . out . println ( arr [ 0 ]);
//System.out.println(arr[5]);
//ArrayIndexOutOfBoundsException
arr [ 2 ] = 10 ;
int [] arr2 = arr ;
System . out . println ( arr2 [ 2 ]);
arr2 = null ;
//System.out.println(arr2[2]);
//NullPointerException
/*
String s = null;
s.length();
*/
arr = null ;
}
}
 

6.2 常用数组操作

数组遍历问题

 

public class Sample {
public static void main ( String [] args ) {
int [] arr = new int []{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
//String str str.length()- 函数
//int[] arr arr.length- 属性
for ( int i = 0 ; i < arr . length ; i ++ ) {
arr [ i ] = arr [ i ] * 10 ;
System . out . println ( arr [ i ]);
}
// 通过角标遍历 可以在遍历的过程中对指定的元素进行修改
//foreach 遍历 主要针对的是一些可迭代对象 Iterable
/*
for ( 数据类型 变量名 : 可迭代容器 ) {
}
*/
for ( int num : arr ) {
//num -> arr[i]
num = num / 10 ;
System . out . println ( num );
}
// 这种遍历方式 只能获取元素,不能修改元素
for ( int i = 0 ; i < arr . length ; i ++ ) {
System . out . println ( arr [ i ]);
}
}
}

数组最值问题

 

public class Sample {
public static void main ( String [] args ) {
int [] arr = new int []{ 3 , 6 , 8 , 2 , 9 , 4 , 5 , 1 , 7 };
int min = arr [ 0 ];
int max = arr [ 0 ];
for ( int i = 1 ; i < arr . length ; i ++ ) {
if ( arr [ i ] < min ) {
min = arr [ i ];
}
if ( arr [ i ] > max ) {
max = arr [ i ];
}
}
System . out . println ( max );
System . out . println ( min );
}
}
 

数组扩容问题

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 ;
}
}

 

选择排序算法

public class Sample {
// 选择排序
public static void main ( String [] args ) {
int [] arr = { 8 , 9 , 2 , 6 , 7 , 1 , 4 , 5 , 3 };
for ( int i = 0 ; i < arr . length - 1 ; i ++ ) { //-1 n 个数字没有第 n
for ( int j = i + 1 ; j < arr . length ; j ++ ) {
if ( arr [ i ] > arr [ j ]) {
swap ( arr , i , j );
}
}
}
print ( arr );
}
//[1, 2, 3, 4, 5]
public static void print ( int [] arr ) {
System . out . print ( "[" );
for ( int i = 0 ; i < arr . length ; i ++ ) {
System . out . print ( arr [ i ]);
if ( i == arr . length - 1 ) {
System . out . println ( "]" );
} else {
System . out . print ( ", " );
}
}
}
public static void swap ( int [] arr , int i , int j ) {
int temp = arr [ i ];
arr [ i ] = arr [ j ];
arr [ j ] = temp ;
}
}
 
 

冒泡排序算法

 

public class Sample {
// 冒泡排序
public static void main ( String [] args ) {
int [] arr = { 8 , 9 , 2 , 6 , 7 , 1 , 4 , 5 , 3 };
for ( int i = 0 ; i < arr . length - 1 ; i ++ ) { //-1 表示 n 个数字只有 n-1
for ( int j = 0 ; j < arr . length - 1 - i ; j ++ ) { //-1 避免重复比较 ( 当前最大和上一
轮最大 )
if ( arr [ j ] > arr [ j + 1 ]) {
swap ( arr , j , j + 1 );
}
}
}
print ( arr );
}
public static void print ( int [] arr ) {
System . out . print ( "[" );
for ( int i = 0 ; i < arr . length ; i ++ ) {
System . out . print ( arr [ i ]);
if ( i == arr . length - 1 ) {
System . out . println ( "]" );
} else {
System . out . print ( ", " );
}
}
}
public static void swap ( int [] arr , int i , int j ) {
int temp = arr [ i ];
arr [ i ] = arr [ j ];
arr [ j ] = temp ;
}
}
 
 

插入排序算法

 

public class Sample {
// 插入排序
public static void main ( String [] args ) {
int [] arr = { 8 , 9 , 2 , 6 , 7 , 1 , 4 , 5 , 3 };
for ( int i = 1 ; i < arr . length ; i ++ ) {
int e = arr [ i ];
int j = 0 ;
for ( j = i ; j > 0 && arr [ j - 1 ] > e ; j -- ) {
arr [ j ] = arr [ j - 1 ];
}
arr [ j ] = e ;
}
print ( arr );
}
public static void print ( int [] arr ) {
System . out . print ( "[" );
for ( int i = 0 ; i < arr . length ; i ++ ) {
System . out . print ( arr [ i ]);
if ( i == arr . length - 1 ) {
System . out . println ( "]" );
} else {
System . out . print ( ", " );
}
}
}
}
 
 
 

计数排序算法

 

public class Sample {
// 计数排序
public static void main ( String [] args ) {
int [] arr = { - 2 , 9 , - 1 , 12 , 8 , - 3 , 6 , 7 , 4 , 5 , 2 , 1 , 0 , 8 , 6 , 7 , 4 , - 3 , - 2 , - 1 , - 1 , 7 };
int min = arr [ 0 ];
int max = arr [ 0 ];
//O(n)
for ( int i = 1 ; i < arr . length ; i ++ ) {
if ( arr [ i ] < min ) {
min = arr [ i ];
}
if ( arr [ i ] > max ) {
max = arr [ i ];
}
}
int [] temp = new int [ max - min + 1 ];
// 对应关系 index = number - min number = index + min
//O(n)
for ( int i = 0 ; i < arr . length ; i ++ ) {
temp [ arr [ i ] - min ] ++ ;
}
//temp[index] 表示 index 对应的数字 number 出现的次数
int k = 0 ;
//O(n)
for ( int index = 0 ; index < temp . length ; index ++ ) {
while ( temp [ index ] != 0 ) {
arr [ k ] = index + min ;
k ++ ;
temp [ index ] -- ;
}
}
print ( arr );
}
public static void print ( int [] arr ) {
System . out . print ( "[" );
for ( int i = 0 ; i < arr . length ; i ++ ) {
System . out . print ( arr [ i ]);
if ( i == arr . length - 1 ) {
System . out . println ( "]" );
} else {
System . out . print ( ", " );
}
}
}
}
 

 

基数排序算法

import java . util . LinkedList ;
public class Sample {
// 基数排序
public static void main ( String [] args ) {
int [] arr = { 102 , 203 , 321 , 13 , 12 , 78 , 96 , 34 , 37 , 28 , 6 , 8 , 5 , 6 };
//1. 先找到最大值 决定轮数
int max = arr [ 0 ];
for ( int i = 0 ; i < arr . length ; i ++ ) {
if ( arr [ i ] > max ) {
max = arr [ i ];
}
}
int radex = ( 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 ); // 获取数字的 r 位 返回该数字要去的桶的角标 0~9
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 ();
}
}
}
print ( arr );
}
public static int getIndex ( int number , int r ) {
//123 r=0
//123 r=1
//123 r=2
int index = 0 ;
for ( int i = 0 ; i <= r ; i ++ ) {
index = number % 10 ;
number /= 10 ;
}
return index ;
}
public static void print ( int [] arr ) {
System . out . print ( "[" );
for ( int i = 0 ; i < arr . length ; i ++ ) {
System . out . print ( arr [ i ]);
if ( i == arr . length - 1 ) {
System . out . println ( "]" );
} else {
System . out . print ( ", " );
}
}
}
}
 
 
 

二分查找算法(注:所查找的数据必须是有序的)

 

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 );
}
}
 

 

可变长参数列表

public class Sample {
public static void main ( String [] args ) {
show ( 1 );
show ( 1 , 2 , 3 );
show ( "hehe" , "lala" , "haha" , "xixi" , "heihei" );
}
public static void show ( int ... nums ) {
for ( int i = 0 ; i < nums . length ; i ++ ) {
System . out . print ( nums [ i ] + " " );
}
System . out . println ();
}
public static void show ( String ... strs ) {
for ( int i = 0 ; i < strs . length ; i ++ ) {
System . out . print ( strs [ i ] + " " );
}
System . out . println ();
}
}
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值