Day05JavaSE——数组&递归

数组&递归

数组概述

  • 数组类似于一个容器,是内存空间中开辟出来的一个区域,这个区域用来存储多个同一数据类型的数据,这样避免了当大量变量数据需要使用时需要对每个数据进行声明。只要是数据类型相同都可以放进同一个数组空间。此时每个数据都称为这个数组内的元素。
  • 常用的数组分为一维数组和二维数组,当然也存在三维数组,但是在日常应用中我们应用最多的时一维数组和二维数组。

注意:数组是存储多个变量(元素)的缓存空间(容器),同一数组内元素变量的数据类型一致

  • 数组可以存储基本数据类型,也可以存储引用数据类型
  • 基本数据类型(四类八种)
  • 应用数据类型:数组,类,接口,枚举等

一维数组

  • 声明一维数组的语法格式
    数组元素类型 数组名字[];

    int arr[];

  • 数组元素类型[] 数组名字;

    String str[];

数组声明后还无法直接访问他的元素,因为你只是声明了一个int型的名叫arr的数组,但是并没有为数组分配内存空间,这时我们需要用new关键字来为数组分配内存空间。

  • 数组名称 = new 数组元素的类型[数组元素的个数]

  • new关键字为数组分配内存时

    整形数组的初始值都为0

    浮点型数组的初始值都是0.0

    布尔类型的初始值都是false

    char型数组的初始值都是空格字符(\u0000*)

定义一个数组的日常使用语法格式是:数据类型[] = 数组名=new 数组类型[数组长度];

数组初始化

为数组中的数组元素分配内存空间,并为每个数组元素赋值

  • 动态初始化:只指定长度,由系统给出初始化值;
  • 静态初始化:给出初始化值,由系统分配合适的长度;

    数据类型[] 数组名={元素间用”,“隔开};

案例演示

案例A:打印数组

public class array {
    public static void main(String[] args) {
        int[] arr = new int[3];
        arr[0]=10;
        arr[1]=20;
        arr[2]=30;
        System.out.println(arr);        //打印arr数组地址
        for(int i=0;i<=arr.length-1;i++){
            System.out.println(arr[i]);
        }
    }
}

Java中内存分配以及栈(Stack)和堆(Heap)的区别

  • 栈内存:用于存储局部变量,当数据使用完后,所占空间会自动释放
  • 堆内存
    1、数组和对象,通过new建立的实例都存放在堆内存内
    2、每个实体都有内存地址值
    3、实体中的变量都有默认初始化值
    4、实体不被使用会在不确定的时间内被垃圾回收器回收
    
  • 一维数组内存图解

二维数组

什么是二维数组?

​ 二维数组就是有一个一维数组a,这个a中的每一个元素都是一个一维数组,此时我们称其为二维数组(学过线性代数的都知道,其实二维数组可以看做定义了一个m行n列的矩阵)

二维数组的语法格式

格式一:

数据类型[][] 变量名 = new 数据类型[m] [n]
m表示这个二维数组有几个一维数组(必写项)
n表示每一个一维数组的元素个数(可选)
int[][] arr = new int[3] [2];
定义了一个二维数组arr
这个二维数组有3个一维数组,名称是arr[0],arr[1],arr[2]
每个一维数组有2个元素,可以通过arr[m] [n]来获取
表示获取第m+1个一维数组的第n+1个元素

格式二:

数组类型[] [] 变量名 = new 数据类型[m] [];

m表示这个二维数组中一维数组的个数

这次没有给出一维数组元素的个数,可以动态给出

int[][] arr = new int[3][];		//引用数据,内赋值null
arr[0] = new int[2];			//这里给arr[0],arr[1],arr[2]的是地址
arr[1] = new int[5];
arr[2] = new int[4];

格式三

数据类型[] [] 变量名 = new 数据类型[] []{{元素……},{元素……},{元素……},{元素……}···};

简化版:

​ 数据类型[] [] 变量名 = {{元素……},{元素……},{元素……}};

这个格式属于静态初始化,由我们指定具体元素值,由系统分配长度

注意事项

以下格式也可以表示二维数组
a:数据类型 数组名[][] = new 数据类型[m][n];
b:数据类型[] 数组名[] = new 数据类型[m][n];
这两种格式不推荐使用
注意下面定义的区别
int x,y;
int[] x,y[];

	区别是:
	 int[] x,y[];//定义了两个数组 一个是一维数组x 一个是二维数组y
	  x=new int[3];	
	  y=new int[3][];

案例演示

  • 定义一个二维数组,输出二维数组的名称和二维数组的的每一个一维数组,然后动态给二维数组赋值一维数组
    再次输出二维数组中的每一个一维数组,给二维数组中的元素赋值,输出对应的元素值
  • public class TwoDimension {
        public static void main(String[] args) {
            System.out.println("------------二维数组的创建及使用-----------");
    
    
            System.out.println("--初始化二维数组--");
            //动态初始化,指定长度
            //格式一
            int arrDemo1[][] = new int[3][4];
            
            //格式二
            int[][] arrDemo3=new int[3][];
            arrDemo3[0]=new int[2];
            arrDemo3[1]=new int[5];
            arrDemo3[2]=new int[4];
            
            //格式三
            //静态初始化,JVM自动分配内存长度
            int arrDemo2[][] = {{1}, {2, 3}, {4, 5, 6}};
            //输出第一个二维数组的地址
            System.out.println(arrDemo1);
            System.out.println();
            //将二维数组arrDemo1中的第二个一维数组中的第四个元素赋值5
            arrDemo1[1][3] = 5;
    
            //输出二维数组的两个元素
            System.out.println(arrDemo1[1][3]);
            System.out.println(arrDemo1[0][2]);
    
            //遍历输出第一个二维数组,结果为0阵列,其中第三行,第四列为5
            //二维数组的遍历是需要两个循环嵌套,外循环作为行遍历,内循环作为列遍历
            for (int i = 0; i <= arrDemo1.length - 1; i++) {
                for (int j = 0; j <= arrDemo1[i].length - 1; j++) {
                    System.out.print(arrDemo1[i][j]);
                }
                System.out.println();
            }
            System.out.println();
    
            //输出arrDemo2
            for (int i = 0; i <= arrDemo2.length - 1; i++) {
                for (int j = 0; j <= arrDemo2[i].length - 1; j++) {
                    System.out.print(arrDemo2[i][j]);
                }
                System.out.println();
            }
            System.out.println();
    
            //输出arrDemo1的以为变量地址
            for (int i = 0; i <= arrDemo1.length - 1; i++) {
                System.out.println(arrDemo1[i]);
            }
        }
    }
    
  • 输出杨辉三角

            1
            1  1
            1  2  1
            1  3  3  1
            1  4  6  4  1
            1  5  10 10 5  1
    
import java.util.Scanner;

public class myTest2 {
    public static void main(String[] args) {
        /*需求:打印杨辉三角形(行数可以键盘录入)
      1
      1 1
      1 2 1
      1 3 3 1
      1 4 6 4 1
      1 5 10 10 5 1*/

        /*分析:杨辉三角的特点
        * 1、每一行的首,尾都是1
        * 2、从第三行开始,每一行的中间数字=同一列上一行的数字+前一列上一行的数字*/

        Scanner sc = new Scanner(System.in);
        System.out.println("请录入行数");
        int n = sc.nextInt();
        int num[][] = new int[n][n];

        //第一个和最后一个都是1
        for (int i = 0; i < num.length; i++) {
                num[i][0] = 1;
                num[i][i] = 1;                    //num[i][num[i].length-1]=1;    不对
            }

            //从第三行开始才有中间值
        // 中间值的算法,从第三行开始,中间的值=同列上一行+上一行前一列
            for (int i = 2; i < num.length; i++) {
                for (int j = 1; j < i; j++) {
                    num[i][j]=num[i-1][j]+num[i-1][j-1];
                }
            }
            //打印三角形
        for (int i = 0; i < num.length; i++) {
            for (int j = 0; j <= i; j++) {
                System.out.print(num[i][j]+"  ");
            }
            System.out.println();
        }
    }
}

数组的操作

数组的操作包括获取最值,遍历,反转,查表法,基本查找

案例:利用建立功能方法并且调用,实现数组内求最大值,最小值,打印数组元素,将数组内元素反转

//数组遍历循环的快捷键arr.length-1.forr
        //数组反向遍历
        /*for(i=length-1;i>=0;i--)*/
public class MyTest {
    public static void main(String[] args) {
        int[] arr={100,200,300,400,500,600,50};
        int max=getMax(arr);
        System.out.println(max);
        int min=getMin(arr);
        System.out.println(min);
        showArr(arr);
        reversalArr(arr);
    }
    //计算最大值
    public static int getMax(int[] arr){
        int max=arr[0];
        for(int i=0;i<=arr.length-1;i++){
            if(max<arr[i]){
                max=arr[i];
            }
        }
        return max;
    }
    //计算最小值
    public static int getMin(int[] arr){
        int min=arr[0];
        for(int i=0;i<=arr.length-1;i++){
            if(min>arr[i]){
                min=arr[i];
            }
        }
        return min;
    }
	//打印数组元素
    public static void showArr(int[] arr){
        for(int i=0;i<=arr.length-1;i++){
            System.out.print(arr[i] + ",");
        }
        System.out.println();

    }
    //反转数组元素
    public static void reversalArr(int[] arr){
        for (int i =0 ; i <= arr.length/2 - 1; i++) {
            int t=0;
            t=arr[i];
            arr[i]=arr[arr.length-1-i];
            arr[arr.length-1-i]=t;
        }
        for (int j = 0; j <= arr.length-1; j++) {
            System.out.print(arr[j]+",");
        }
        //将数组内元素的位置调换(方法二)
       /* for(int i=0,int j=arr.length-1;i<j;i++,j--){

        }*/
        System.out.println();
    }
}
/*A:
         * 案例演示:
         * 根据键盘输入索引,查找对应星期*/
        //查表法
        //根据索引找对应元素
import java.util.Scanner;
public class MyTest2 {
    public static void main(String[] args) {
       
        String[] week = {"星期一", "星期二", "星期三", "星期四", 
                         "星期五", "星期六", "星期天"};
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入索引0-6");
        int index=sc.nextInt();
        String ele = getElement(index,week);
        System.out.pringln(ele);
    }
	private static String getElement(int index ,String[] week){
        if(index >= 0 && index <= 6){
            String str = week[index];
            return str;
        }else{
            return "error";
        }
    } 
}


//根据元素查对应的索引
import java.util.Scanner;

public class MyTest3 {
    public static void main(String[] args) {
        String[] week = {"星期一", "星期二", "星期三", "星期四",
                         "星期五", "星期六", "星期日"};
        //根据元素查对应的索引
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入星期一----星期天");
        String s = sc.nextLine();
        int index = getNum(s, week);
        System.out.println("该元素对应的索引是" + index);
    }

    private static int getNum(String s, String[] week) {
        int index = -1;
        for (int i = 0; i <= week.length - 1; i++) {
            if (week[i].equals(s)) {      //此处判断不能用week[i]==s,这样可能会出错
                index = i;
                break;
            }
        }
        return index;
    }
}
/*键盘输入月份
输出每个月有多少天*/
import java.util.Scanner;

public class myTest4 {
    public static void main(String[] args) {
        int dayNum[] = {31,28,31,30,31,30,31,31,30,31,30,31};
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入月份");
        int month = sc.nextInt();
        int day = getDay(month,dayNum)-1;
        System.out.println(month+"月有"+day+"天");
        getDay(dayNum);
    }
    public static int getDay(int month,int[] dayNum){
        if(month >= 0 && month <= 12){
            int day = dayNum[month];
            return day;
        }else{
            return 404;
        }
    }
    public static void getDay(int[] dayNum){
        for(int i = 0;i <= dayNum.length-1;i++){
            System.out.println(i+1+"月有"+dayNum[i]+"天");
        }
    }
}
import java.util.Scanner;

public class MyTest {
    public static void main(String[] args) {
        /*A:案例演示
	        需求:分别输出公司各个季度的总销售额和年销售额
	        某公司按照季度和月份统计的数据如下:单位(万元)
	        第一季度:22,66,44
	        第二季度:77,33,88
	        第三季度:25,45,65
	        第四季度:11,66,99*/
        int[][] annualSales=new int[4][3];
        Scanner sc = new Scanner(System.in);
        
        //输入销售额,并把销售额存入二维数组中,行代表季度,列代表月份
        System.out.println("请输入销售额");
        for(int i=0;i<=annualSales.length-1;i++) {
            for (int j = 0; j <= annualSales[0].length - 1; j++) {
                System.out.println("请输入第"+(i+1) +"季度第"+ (j + 1) + "个月的销售额");
                int money = sc.nextInt();
                annualSales[i][j] = money;
            }
        }
        for(int i=0;i<=annualSales.length-1;i++) {
            for (int j = 0; j <= annualSales[i].length - 1; j++) {

                System.out.print(annualSales[i][j]+", ");
            }
            System.out.println();
        }
        
        //计算每个季度的收入
        int yearSales=0;
        for(int i=0;i<=annualSales.length-1;i++){
            int addQuartSales=0;
            for(int j=0;j<=annualSales[i].length-1;j++){
                switch(i){
                    case 0: addQuartSales += annualSales[i][j];
                    break;
                    case 1: addQuartSales += annualSales[i][j];
                    break;
                    case 2: addQuartSales += annualSales[i][j];
                    break;
                    case 3: addQuartSales += annualSales[i][j];
                    break;
                }
            }
            System.out.println("第"+(i+1)+"个季度的总收入为"+addQuartSales);
        }
        
        //计算全年总收入
        for(int i=0;i<=annualSales.length-1;i++) {
            for (int j = 0; j <= annualSales[i].length - 1; j++) {
                yearSales+=annualSales[i][j];
            }
        }
        System.out.println("全年总收入为"+yearSales);
    }
}

参数传递问题

/*A:案例演示
	看程序写结果,并画内存图解释*/
	public static void main(String[] args) {

		int a = 10;
		int b = 20;
		System.out.println("a: " + a + ",b: " + b);			//a=10,b=20
		change(a,b);
		System.out.println("a: " + a + ",b: " + b);			//a=10,b=20

		int[] arr = {1,2,3,4,5};
		change(arr);										//arr[1]=4
		System.out.println(arr[1]);							//arr[3]=8
	}

	public static void change(int a,int b)  {

		System.out.println("a: " + a + ",b: " + b);		//a=10,b=20
		a = b;											//a=20
		b = a + b;										//b=40
		System.out.println("a: " + a + ",b: " + b);		//a=20,b=40
	}

	public static void change(int[] arr){
		for(int x = 0 ; x < arr.length ; x++){
			if(arr[x]%2 == 0){
				arr[x] *= 2;
			}
		}
	}

/*基本类型的参数传递,属于值传递
* 引用类型的参数传递,是将地址值传递过去
* 特点:基本类型作为参数传递,形参的改变不影响实参
*      引用类型作为参数传递,形参的改变会影响实参*/

递归

/*递归:在方法中低啊用方法本身的一种现象
 * 递归需要注意的:
 * 1、递归要有出口,不然就是死递归,死递归会导致栈溢出
 * 2、递归次数不宜过多,过多也会有栈溢出的可能
 * 3、递归体现的是一种拆分合并的思想*/

因为JVM的栈内存大小是固定的,递归要是没有设置合适的出口,死递归就会造成栈溢出错误

递归就是将一个大问题进行拆分,使其变成若干个简单问题的综合,当解决了所有小问题之后,大问题也就解决了,以下画图进行解释

案例分析

  • 计算5!
/*计算5!*/
public class factorial {
    public static void main(String[] args) {
            int r=multiplication(10);
        System.out.println("结果:" + r);
    }
    private static int multiplication(int n){
        if(n==1){
            return 1;
        }else{
            return n*multiplication(n-1);
            /*第一次:5*multiplication(4)
            * 第二次:5*4*multiplication(3)
            * 第三次:5*4*3*multiplication(2)
            * 第四次:5*4*3*2*multiplication(1)
            * 第五次:5*4*3*2*1,返回1*/
        }
    }
}
  • 猴子第一天摘下N个桃子,当时就吃了一半,还不过瘾,就又多吃了一个。第二天又将剩下的桃子吃掉一半,又多吃了一个。以后每天都吃前一天剩下的一半零一个。到第10天在想吃的时候就剩一个桃子了,问第一天共摘下来多少个桃子?并反向打印每天所剩桃子数。
public class GetPeachNumber {
    public static void main(String[] args) {
        /*  第10天桃子数                   1
        *   第9天桃子数         (第10天桃子数+1)*2
        *   第8天桃子数         (第9天桃子数+1)*2
        *   第7天桃子数         (第9天桃子数+1)*2
        *       ……                        ……
        *   第1天桃子数          (第2天桃子数+1)*2  */

        int peachNumber=getPeachNumber(1);
        System.out.println("第一天摘了"+peachNumber+"个桃子");
    }
    private static int getPeachNumber(int n){
        if(n==10){
            return 1;
        }else{
            int sum=0;
            sum=(getPeachNumber(n+1)+1)*2;
            System.out.println("第"+n+"天所剩桃子数为"+sum);
            return sum;
        }

    }
}
  • 需求:兔子问题(斐波那契数列)
    有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?
    由此可见兔子对象的数据是:1 , 1 , 2 , 3 , 5 , 8 …
public class rabbit {
    public static void main(String[] args) {
        /*A:案例演示:  需求:兔子问题(斐波那契数列)
   有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?
   由此可见兔子对象的数据是:1 , 1 , 2 , 3 , 5 , 8 ...*/
        /*1         1
         * 2         1
         * 3         2
         * 4         3
         * 5         5
         * 6         8
         * ...       ...
         * 20       第19个月的兔子对数+第18个月的兔子对数    */
        //递归思考问题需要从所需要求得的结果去思考规律与编程
        int rabbitSum = getRabbitNumber(20);
        System.out.println("第二十个月一共有" + rabbitSum + "对兔子");

        //普通循环方法实现
        int rabbit[] = new int[20];
        rabbit[0] = 1;
        rabbit[1] = 1;
        getRabbitNumber(rabbit);
        System.out.println(rabbit[19]);


    }

    private static int getRabbitNumber(int monthNumber) {
        if (monthNumber == 1 || monthNumber == 2) {
            return 1;
        } else {
            return getRabbitNumber(monthNumber - 1) + getRabbitNumber(monthNumber - 2);
        }
    }

    private static void getRabbitNumber(int[] rabbit) {
        for (int i = 2; i <= rabbit.length - 1; i++) {


                rabbit[i] = rabbit[i - 1] + rabbit[i - 2];

        }
    }
}
  • 有5个人坐在一起,问第5个人多少岁?
    他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。
    问第3个人,又说比第2人大两岁。
    问第2个人,说比第1个人大两岁。最后
    问第1个人,他说是10岁。
    请问第5个人多大?
public class yearAge {
    public static void main(String[] args) {
        /*有5个人坐在一起,问第5个人多少岁?
        他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。
        问第3个人,又说比第2人大两岁。
        问第2个人,说比第1个人大两岁。最后
        问第1个人,他说是10岁。
        请问第5个人多大?*/
        /*分析:
        * 1                 10
        * 2                 第一人年龄+2
        * 3                 第二人年龄+2
        * 4                 第三人年龄+2
        * 5                 第四人年龄+2             */
        System.out.println(getAge(5));


    }
    private static int getAge(int n){
        int fiveAge=0;
        if(n==1){
            return  fiveAge=10;
        }else{
            return fiveAge=(getAge(n-1)+2);
        }

    }
}
public class yearAge {
    public static void main(String[] args) {
        /*有5个人坐在一起,问第5个人多少岁?
        他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。
        问第3个人,又说比第2人大两岁。
        问第2个人,说比第1个人大两岁。最后
        问第1个人,他说是10岁。
        请问第5个人多大?*/
        /*分析:
        * 1                 10
        * 2                 第一人年龄+2
        * 3                 第二人年龄+2
        * 4                 第三人年龄+2
        * 5                 第四人年龄+2             */
        System.out.println(getAge(5));


    }
    private static int getAge(int n){
        int fiveAge=0;
        if(n==1){
            return  fiveAge=10;
        }else{
            return fiveAge=(getAge(n-1)+2);
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值