3.从零开始学习Java-数组

一、数组的概念

一组连续的存储空间,存储多个相同数据类型的值。

特点:

  1. 类型相同
  2. 长度固定

二、数组的声明与赋值

2.1 四种声明方式

1.先声明、再分配空间: 数据类型[] 数组名; 数组名 = new 数据类型[长度];

int [] array1;//先声明
array1 = new int[12];//再分配空间

2.声明并分配空间: 数据类型[] 数组名 = new 数据类型[长度];

int[] array2 = new int[12];

3.声明并赋值(繁): 数据类型[] 数组名 = new 数据类型[]{value1,value2,value3,…};

int[] array3 = new int[]{};

4.声明并赋值(简): 数据类型[] 数组名 = {value1,value2,value3,…}; //显示初始化,注意:不可换行。

int[] array3 = {5,2,0,1,3,1,4};
public class Shuzu {
	public static void main(String[] args) {
		int[] nums = new int[10];//默认值为0
		nums[0] = 0;
		nums[1] = 1;
		nums[2] = 2;
		System.out.println(nums[0]);
		System.out.println(nums[1]);
		System.out.println(nums[2]);
		//-------------
		int [] a;
		a = new int[3];		
		//-------------
		int [] b = new int[] {1,2,3,4,5,6};
		//-------------
		int [] c = {1,2,3,4,5,6};
	}
}

2.2 数组的默认值:

数组默认值:

  • 整数:0
  • 小数:0.0
  • 字符:\u0000
  • 布尔:false
  • 其他:null

三、数组的组成

数组的使用:

下标的范围:不可越界

四、数组的遍历

遍历:从头至尾,逐一对数组的每个元素进行访问。

两种遍历方式:for遍历和for增强。

数组名.length 可动态获得数组长度。

		int [] bs = new int[] {11,22,33,44,55};
		//-------------
		int [] c = {1,2,3,4,5,6};
		for (int i = 0; i < c.length; i++) {//for遍历
			System.out.println(c[i]);
		}
		for (int  some : bs) {//for增强
			System.out.println(some);
		}

给定一个整数数组,读入一个整数n,如果n在数组中存在,输出下标,不存在则输出-1。

public class Mean {
	public static void main(String[] args) {
		int[] array = {12,25,99,99,1,15,25};
		int sum = 0;
		double average = 0;
		for (int i = 0; i < array.length; i++) {
			sum+=array[i];
		}
		average = sum/array.length;
		System.out.printf("%.2f",average);
	}
}

控制台输入5个城市名称,用数组保存,并遍历输出。

// 控制台输入5个城市名称,用数组保存,并遍历输出
public void saveCity() {
    String[] citys = new String[5];
    Scanner scanner = new Scanner(System.in);
    for(int i = 0; i < citys.length; i++) {
        String input = scanner.next();
        citys[i] = input;
    }
    for (String city : citys) {
        System.out.print(city + " ");
    }
}

五、 复制的方式:

  • 循环将原数组中所有元素逐一赋值给新数组。
  • System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度);
  • java.util.Arrays.copyOf(原数组, 新长度);//返回带有原值的新数组。

5.1 第一种方法:循环:

public void arrayCopy1() {
    int[] array1 = {0,2,5};
    int[] array2 = new int[array1.length];
    for(int i = 0; i < array1.length; i++) {
        array2[i] = array1[i];
    }
    for (int value : array2) {
        System.out.print(value + " ");
    }
}

5.2 第二种方法:clone

public class ArrayClone {
	public static void main(String[] args) {
		int [] array1 = {0,2,5};
		int [] array2;
		array2 = array1.clone();//使用clone
		for (int value : array2) {
			System.out.println(value+" ");
		}
	}
}

5.3 第三种方法:Arrays.copyOf()

import java.util.Arrays;
public class ApplyCopy3 {
	public static void main(String[] args) {
		int [] array1 = {5,2,0};
		int [] array2;
		//第一个参数:要复制的数组
		//第二个参数:新数组的大小(如果新长度>原数组长度,则用0填充)
		array2 = Arrays.copyOf(array1, 5);
		for (int value:array2) {
			System.out.print(value+" ");//结果:5 2 0 0 0
		}
	}
}

5.4 第四种方法:Arrays.copyOfRange()

public class ArrayCopy4 {
	public static void main(String[] args) {
		int [] oldArray = {5,2,0,13,14};
		int [] newArray;
		//复制(0,5)的数组元素到新数组中
		//如果复制长度<原数组长度,则就截取部分
		//如果复制长度>原数组长度,则用0填充
		newArray = Arrays.copyOfRange(oldArray, 0, 5);
        //截取的长度
		for (int value : newArray ) {
			System.out.println(value + " ");
		}
	}
}

5.5 第五种方法:System.arraycopy()

public void arrayCopy5() {
    int[] oldArray = {5, 2, 0, 1, 3, 1, 4};
    int[] newArray = new int[oldArray.length];
    // 参数: (原数组 原数组起始下标 新数组 新数组起始下标 复制长度)
    // 也就是从原数组的0位置开始复制,复制到新数组从0开始的位置
    System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
    for (int value : newArray) {
        System.out.print(value + " ");
    }
}

六、 数组的扩容:

1.创建数组时,必须显示指定长度,并在创建之后不可更改长度。

2.扩容的思路:

  • 创建大于原数组长度的新数组。
  • 将原数组中的元素依次复制到新数组中。
	public static void main(String[] args) {
		//数组的扩容
		int [] numbs = new int [] {1,2,3,4,5};
		//1.再创建新的数组,默认值0
		int [] numbs1 = new int [numbs.length*2];
		//2.复制旧数组中的元素到新数组中
		for (int i = 0; i < numbs.length; i++) {
			numbs1[i] = numbs[i];
		}//数组位置变换
		numbs = numbs1;
		for (int i = 0; i < numbs1.length; i++) {
			System.out.print(numbs1[i]+" ");
		}
		System.out.println();
		for (int i:numbs1) {
			System.out.print(i+" ");
		}
	}

七、数组的插入删除:

7.1 插入元素:

首先确定插入元素的位置。

如果在数组末尾,未超出最大角标则直接加入;否则需要后移元素后,加入。

        //插入
        int[] a = {1,2,4,7,5,0,0};//数组下标要足够长,不然插入以后造成下标越界即Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
        Scanner input = new Scanner(System.in);
        System.out.println("请输入一个新的元素:");
        int n = input.nextInt();
        System.out.println("请输入插入元素的位置:");
        int pos = input.nextInt();
        int size = 5;//设置数组有值的长度,便于size++

        if (pos>=0&&pos<=size){
            for (int j=size-1;j>=pos;j--){
                a[j+1] = a[j];
            }
            a[pos]=n;
            size++;
            for (int i : a) {
                System.out.println(i);
            }
        }else{
            System.out.println("输入有误!");
        }

7.2 删除元素:

如果是末尾元素,则直接删除,否则删除后需要前移元素。

        //删除
		int[] a = {1,2,4,7,5,0,0};
        Scanner input = new Scanner(System.in);
        int size = 5;
        System.out.println("请输入删除的位置:");
        int p =input.nextInt();
        if (p>0&&p<size){
            if (p==size-1){
                a[p]=0;
            }else {
                for (int k = p;k<size;k++)
                {
                    a[k] = a[k+1];
                }
                a[size]=0;
            }
            for (int i : a) {
                System.out.println(i);
            }

        }else
        {
            System.out.println("输出有误");
        }

地址的替换:

  • 数组作为引用类型之一,其变量中存储的是数组的地址。
  • 完成元素复制后,需将新数组地址,赋值给原变量进行替换。

八、数组类型的参数:

  • 方法调用时,将nums中的地址赋值给oneArray,此时二者指向同一个数组。

  • 传递参数时:基本类型传递的是变量中的值;

  • 引用类型传递的是变量中的地址。

    如果传递的是基本数据类型,则传递的是值.

    如果传递的是引用数据类型,则传递的是引用.

public static void main(String[] args){
    int[] nums = {111,222,333,444,555};
    printArray(nums);
}

    public static void printArray(int[] array) {
        for (int value : array) {
            System.out.print(value + " ");
        }
    }

8.1 因为数组是引用类型,传递的是引用

数组类型的返回值:

调用数组类型返回值的方法时,方法执行后,返回的是数组的地址。

  • 当在其它地方修改数组时,两者的数据都会变
  • 因为实际上修改的那个数组和此数组指向的内存空间是一个地方,所以修改一个,另一个也会变
public class TestArray4 {
    public static void main(String[] args) {
        int[] nums={18,22,9,16,27,35};
        int n=100;
        printArray(n, nums);
        System.out.println("-----主方法中遍历nums-----");
        for (int i = 0; i < nums.length; i++) {
            System.out.println(nums[i]);
        }
        System.out.println("---------");
        System.out.println(n);//在这里输出的话,数组也会加5,如果是int的话,则不会发生改变。
    }
    public static void printArray(int num,int[] arr){
        System.out.println(num);
        num=200;
        System.out.println("-------遍历数组-------");
        for (int i : arr) {
            System.out.println(i);
        }
        System.out.println("每个元素加5");
        for (int i = 0; i < arr.length; i++) {
            arr[i]=arr[i]+5;//如果是int类型的数,这地方syso才会有元素加5,但是如果是数组的话,一个地方加了5,在堆中就会加5,所有每个地方的数组都加5,数组是引用类型。
        }
    }
}

8.2 可变长参数:

概念:可接收多个同类型实参,个数不限,使用方式与数组相同。

语法:数据类型… 形参名

  • 必须定义在形参列表的最后
  • 且只能有一个

用for循环来创建可变长参数。

可变长参数可以用来存储数组,或一段数。

  public class LongArgs{
      	public static void main(String[] args){
		int [] x = {1,2,3,4,5};
        printArray(5,x);
    }

    public static void printArray(int n,int ...arr) {
        for (int i : arr) {
            System.out.println(i);
        }
    }
}
输出:
1
2
3
4
5   
  public class LongArgs2{
      	public static void main(String[] args){
		int [] x = {1,2,3,4,5};
        printArray(5,500,400,300,200,100);
    }

    public static void printArray(int n,int ...arr) {
        for (int i : arr) {
            System.out.println(i);
        }
    }
}
输出:
500
400
300
200
100

九、 数组的排序

9.1 冒泡排序:

相邻的两个数值比较大小,互换位置。

//冒泡算法:两个相邻的元素进行比较,小的向前,大的向后
//n个数字来排列,两两比较小靠前,外层循环n-1,内层循环n-1-i;
public class Maopao {
	public static void main(String[] args) {
		int[] nums= {20,8,19,15,23,80,13};
		System.out.println("排序之前:");
		for (int a : nums ) {
			System.out.print(a+",");
		}
		System.out.println();
		bubbleSort(nums);
		System.out.println("排序之后:");
		for (int b : nums) {
			System.out.print(b+",");
		}	
	}
	public static void bubbleSort(int[] arr) {
		for(int i =0; i<arr.length-1;i++) {
			for (int j = 0; j < arr.length-i-1; j++) {
				if (arr[j]>arr[j+1]) {
					int t= arr[j];
					arr[j] = arr[j+1];
					arr[j+1]= t;
					
				}
			}
		}
	}
}
    public static void bubbleSort(int[] sums) {
        for (int i = 0; i < sums.length-1; i++) {
            boolean flag = true; 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。
            for (int j = 0;j < sums.length-i-1;j++){
                if (sums[j]>sums[j+1]){
                    int t = sums[j];
                    sums[j] = sums[j+1];
                    sums[j+1] = t;
                    flag = false;
                }
            }
            if (flag){
                break;
            }
        }
        for (int sum : sums) {
            System.out.println(sum);
        }
    }

9.2 选择排序:

固定值与其他值依次比较大小,互换位置。

//选择排序:选择一个元素,让选择依次和后面的元素进行比较,小的向前,大的向后

    //选择排序
    public static void  selectSort(int[] arr){
        for(int i=0;i<arr.length-1;i++){//总共需要比较N-1轮。这是代表的轮数
            for(int j=i+1;j<arr.length;j++){
                if(arr[i]>arr[j]){
                    int t=arr[i];
                    arr[i]=arr[j];
                    arr[j]=t;
                }
            }
        }
    }
    //优化选择排序
    public static void SelectionSort (int [] sums){
        //总共要比较N-1轮
        for (int i = 0; i < sums.length-1; i++) {
            int min = i;
            //每轮需要比较的次数N-i
            //下标进行比较
            for (int j = i+1;j < sums.length ;j++){
                if (sums[j] < sums[min]){
                    //记录目前能找到的最小值元素的下标
                    min = j;
                }
            }
            //将找到的最小值和i位置所在的值进行交换
            //如果i不等于最小值,将此时此时的最小值min与i交换,这样就能保证i为最小值。
            if (i!=min){
                int t = sums[i];
                sums[i] = sums[min];
                sums[min] = t;
            }
        }
        for (int sum : sums) {
            System.out.println(sum);
        }
    }

9.3 插入排序:

将一个记录插入到已经排好序的有序表中。

//插入排序:从第二元素开始,向前找到插入的位置,保证前面的元素都有顺序,因为第一个元素默认是有序的。
//插入排序
    public static void insertSort(int[] arr){
        for(int i=1;i<arr.length;i++){
            for(int j=i-1;j>=0;j--){
                if(arr[j]>arr[j+1]){
                    int t=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=t;
                }
            }
        }
    }
    //优化插入排序
    public static void insertSort2(int[] arr){
        for(int i=1;i<arr.length;i++){
           int t=arr[i];
           int pos=i-1;
           while(pos>=0&&arr[pos]>t){
                arr[pos+1]=arr[pos];
                pos--;
           }
           arr[pos+1]=t;
        }
    }

9.4 JDK排序:

java.util.Arrays.sort(数组名); //JDK提供(升序)。

本身提供的升序。

import java.util.Arrays;

/**
* 使用jdk中提供的排序方式
*
*/
public class TestArray11 {

public static void main(String[] args) {
int[] a = {4,2,7,3,6};

//对数组进行排序
Arrays.sort(a);

//升序输出
// for(int i=0; i<a.length; i++) {
// System.out.println(a[i]);
// }

//降序输出
for(int i=a.length-1; i>=0; i--) {
System.out.println(a[i]);
}

}

}

9.5 希尔排序:

Shell’s Sort,又称“缩小增量排序“,该算法由希尔1959年公布。 • 是直接插入排序算法的一种更高效的改进版本。

9.6 快速排序:

通过一趟排序将要排序的数据分割成独立的两部分;

其中一部分的所有数据都比另外一部分的所有数据都要小;

然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以 此达到整个数据变成有序序列

十、 查找

顺序查找:从头开始遍历所有元素,找出满足条件的数据。
二分查找:二分查找的前提是数据必须有序。

折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。它的基本思想是:(这里假设数组元素呈升序排列)将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止;如果x<a[n/2],则我们只要在[数组]a的左半部继续搜索x;如果x>a[n/2],则我们只要在数组a的右半部继续搜索x。

//二分查找
public class TestArray7 {

    public static void main(String[] args) {
        int[] arr={10,38,65,97,76,13,27,49,78,34,12,64,1};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        int i = binarySearch(arr, 50);
        System.out.println(i);

        //Arrays.binarySearch(, )

    }

    public static int binarySearch(int[] arr,int key){
        int low=0;
        int upper=arr.length-1;
        while(low<=upper){
            int mid=(low+upper)>>>1;
            if(key<arr[mid]){
                upper=mid-1;
            }else if(key>arr[mid]){
                low=mid+1;
            }else{
                return mid;
            }
        }

        return -1;
    }
}
public static int binarySearch(Integer[] srcArray, int des) {
    //定义初始最小、最大索引
    int start = 0;
    int end = srcArray.length - 1;
    //确保不会出现重复查找,越界
    while (start <= end) {
        //计算出中间索引值
        int middle = (end + start)>>>1 ;//防止溢出
        if (des == srcArray[middle]) {
            return middle;
        //判断下限
        } else if (des < srcArray[middle]) {
            end = middle - 1;
        //判断上限
        } else {
            start = middle + 1;
        }
    }
    //若没有,则返回-1
    return -1;
}

十一、 二维数组

一维数组中的一维数组;数组中的元素,还是数组

行数代表一位数组的个数,列数代表一位数组中的元素。

// 二维数组
public void ArrayTwoTest() {
    // 创建二维数组
    int[][] array = new int[5][5];
    
    // 先声明,再分配空间
    int[][] array1;
    array1 = new int[3][3];

    // 创建二维数组并赋值
    int[][] array2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

    // 访问二维数组
    System.out.println(array[0][1]);

    // 二维数组赋值
    array[2][2] = 12;
    array[1][3] = 25;

    // 二维数组的遍历
    for(int i = 0; i < array.length; i++) {
        for(int j = 0; j < array[i].length; j++) {
            System.out.print(array[i][j] + " ");
        }
        System.out.println();
    }
}
int [][] nums = {{1,2,3},{4,5},{6,7,8}};
System.out.println(nums[1][1]);
结果输出:5

十.数组的内存:

程序运行中有两块重要的存储空间。

栈:

  • 存储基本类型数据以及引用类型的地址。
  • 空间比较小,存储速度较快,jdk1.5之前256k,之后1M。
  • 后进先出。

  • 存储引用类型的实际数据。
  • 空间比较大,存储速度较慢。

数组是引用类型,实际存储在堆中,栈中存储数据的引用(地址)。

十二、 扩展:

11.1 native 关键字:

本地方法,没有实现的方法,有JVM提供的实现,有C、C++实现。

11.2 使用Arrays.toString(数组)可以直接输出数组中的值。

Scanner sc = new Scanner(System.in);
		//动态创建数组
		int[] arr = new int[sc.nextInt()];
		for(int i = 0 ; i< arr.length ; i++){
			arr[i] = sc.nextInt();
		}
		/********** Begin **********/
        for(int i = 0;i<arr.length-1;i++){//执行n-1轮比较
            for(int j = i;j<arr.length-1;j++){
                if(arr[i]<arr[j+1]){
                    int temp =arr[i];
                    arr[i] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));

11.3 输出两位小数:

System.out.printf("%.2f", average);

11.4 数组的应用(杨辉三角)

public class Practice04 {

    public static void main(String[] args) {
        int[][] nums=new int[7][];

        for(int i=0;i<nums.length;i++){
            nums[i]=new int[i+1];
            //元素赋值
            for(int j=0;j<nums[i].length;j++){
                if(j==0||i==j){
                    nums[i][j]=1;
                }else{
                    nums[i][j]=nums[i-1][j]+nums[i-1][j-1];
                }
                System.out.print(nums[i][j]+"  ");
            }

            System.out.println();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值