递归
A方法调用B方法,我们很容易理解
递归就是:A方法调用A方法,就是自己调用自己
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
递归结构包括两个部分:
递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
递归体:什么时候需要调用自身方法。
边界条件:边界
前阶段:
返回阶段: n*(n-1)
java:栈机制 (能不用递归就不用递归)
package com.xu.method;
public class demo07 {
//2! 2*1
//5! 5*4*3*2*1
//递归思想
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n){
if(n==1){
return 1;
}else {
return n*f(n-1);
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/a23806b49d98a9d940630102333af1bc.png)
数组
数组的定义
数组是相同类型数据的有序集合
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们
数组声明创建
*首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[ ] arrayReFVar; //首选的方法
或
dataType arrayReFVar[ ] ; //效果相同,但不是首选方法
*Java语言使用new操作符来创建数组,语法如下:
dataType[ ] arrayReFVar = new dataType[ arraySize];
*数组的元素是通过索引访问的,数组索引从0开始。
获取数组长度: arrays.length
package com.xu.array;
public class arraydemo01 {
//变量的类型 变量的名字 = 变量的值;
//数组类型
public static void main(String[] args) {
int[] nums;//1声明一个数组
int nums2[];//知道即可,c和c++中使用较多
nums = new int[10];//2.创建一个数组
//这里面可以存放10个int类型的数字
//3.给数组元素中赋值
nums[0]=1;
nums[1]=2;
nums[2]=3;
nums[3]=4;
nums[4]=5;
nums[5]=6;
nums[6]=7;
nums[7]=8;
nums[8]=9;
nums[9]=10;
//计算所有元素的和
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum = sum +nums[i];
}
System.out.println("总和为:"+sum);
}
}
第一步: int[ ] nums; //声明一个数组
第二步: nums = new int[10]; //创建一个数组
第三步:可以逐个赋值,也可以用for循环遍历输入 //给数组元素中赋值
把第一步和第二步合并:
int[] nums2 = new int[10];
![](https://i-blog.csdnimg.cn/blog_migrate/cf864a2298c1c0a76f1fd57b6e1445d9.png)
内存分析
Java内存分析:
Java内存 :
堆:(1)存放new的对象和数组
(2)可以被所有的线程共享,不会存放别的对象引用
栈:(1)存放基本变量类型(会包含这个基本类型的具体数值)
(2)引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区:(1)可以被所有的线程共享
(2)包含了所有的class和static变量
三种初始化状态
*静态初始化
int[] a ={1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2) };
*动态初始化
int[]a = new int[2];
a[0]=1;
a[1]=2;
*数组的默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每人元素也被按照实例变量同样的方式被隐式初始化。
package com.xu.array;
public class arraydemo02 {
public static void main(String[] args) {
//静态初始化:创建+赋值
int[] a={1,2,3,4,5,6,7,8};
//Man[] mans = {new Man(),new Man()};
System.out.println(a[0]);
//动态初始化:包含默认初始化
int[] b = new int[10];
b[0] = 10;
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
}
}
b[1],b[2]默认值为0.
![](https://i-blog.csdnimg.cn/blog_migrate/f3facfc521eeee53e7891ecd1c6c73de.png)
数组的四个基本特点
*其长度是确定的。数组一旦被创建,它的大小就是不可改变的。
*其元素必须是相同类型,不允许出现混合类型。
*数组中的元素可以是任何数据类型,包括基本类型和引用类型
*数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组边界
下标和合法区间:[0,length-1],如果越界就会报错;
public static void main(String[] args){
int[] a = new int[2];
System.out.println(a[2]);
}
![](https://i-blog.csdnimg.cn/blog_migrate/97dad4395c3267b9c771bf15a461ed72.png)
ArrayIndexOutOfBoundsException: 数组下表越界异常!
小结:
*数组是相同数据类型(数据类型可以为任意类型)的有序集合
*数组也是对象。数组元素相当于对象的成员变量
*数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutOfBounds
数组使用
For-Each循环
数组作方法入参
数组作返回值
数组中经常使用for循环进行遍历
package com.xu.array;
public class demo03 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
//打印全部的数组元素
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
System.out.println("===================");
//计算所有元素的和
int sum=0;
for (int i = 0; i < arrays.length; i++) {
sum=sum+arrays[i];
}
System.out.println("sum="+sum);
//查找最大元素
int max =arrays[0];
for (int i = 0; i < arrays.length; i++) {
if(arrays[i]>max){
max=arrays[i];
}
}
System.out.println("最大值为"+max);
}
}
我们在这次操作中对数组进行了遍历输出,累加以及输出最大值。
![](https://i-blog.csdnimg.cn/blog_migrate/1c443317f36d0bda4c62d7a4d2d2ce3e.png)
下面我们使用一种增强型for循环
package com.xu.array;
public class arraydemo04 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
//JDK1.5 增强型for循环,没有下标
for (int array : arrays) {
System.out.println(array);
}
}
}
在这里我们使用了一种新的for循环
使用数组名.for(arrays.for)
具体格式:for (int array : arrays){}
具体实例:
package com.xu.array;
public class arraydemo04 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
printarray(arrays);
System.out.println(" ");
int[] reverse = reverse(arrays);
printarray(reverse);
}
//打印数组元素
public static void printarray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i]+" ");
}
}
//反转数组
public static int[] reverse(int[]arrays){
int[] result =new int [arrays.length];
//反转的操作
for (int i = 0,j=result.length-1; i <arrays.length; i++,j--) {
result[j]=arrays[i];
}
return result;
}
}
我们写了两个方法,一个是遍历读出数组中的元素,另一个是反转数组
两个方法中,数组作方法入参
在反转数组的方法中,数组也作为了返回值
![](https://i-blog.csdnimg.cn/blog_migrate/bcff603d3d25c38449886ec8c455e5cb.png)
多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
二维数组:
int a[][] = new int[2][5];
解析:以上二维数组a可以看成一个两行五列的数组。
package com.xu.array;
public class arraydemo05 {
public static void main(String[] args) {
//[4][2]
/*
1,2 array[0]
2,3 array[1]
3,4 array[2]
4,5 array[3]
*/
int[][] array= {{1,2},{2,3},{3,4},{4,5}};
printarray();
}
//打印数组元素
public static void printarray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i]+" ");
}
}
}
假如我们直接输出array[0],输出的是他的地址
![](https://i-blog.csdnimg.cn/blog_migrate/ffd7ffe9858cc170900f278cf14c31c6.png)
如果要查看里面的值,我们可以
![](https://i-blog.csdnimg.cn/blog_migrate/1e3b13f393257e46c405f8ece75c7c2f.png)
或者我们选择使用打印的方法。
我们调用打印的方法,打印array,发现报错了
![](https://i-blog.csdnimg.cn/blog_migrate/b392938e0888d43704abbb7b607e4052.png)
原因:不兼容的类型: int[][]无法转换为int[]
我们只需要将array改成array[0]即可
![](https://i-blog.csdnimg.cn/blog_migrate/acc6203bfa29742678a8a9d38ef6ada6.png)
二维数组使用for循环的遍历输出(循环里套循环)
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.println(array[i][j]);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/dc1eee7a53fbcbb614fdfab75f3a0cd2.png)
使用双层for循环巧妙实现
明天我们将会进行扩展 arrays类,冒泡排序以及稀疏数组