6.数组

第6章 数组

6.1 数组的概念及定义

数组是用来存储数据的集合,通常我们会发现把数组看作一个存储具有相同类型 的变量集合会更有用,无须声明单个变量

数组主要用于解决大量数据计算与存储的问题

每一个数组而言,都是存在堆内存当中,每一个数组都是一个对象

创建数组:

创建数组变量未赋值时会有默认值,默认值时元素类型的0值;

当给数组分配空间时,必须指定该数组能够存储的元素个数,从而确定数组大小;

创建数组之后就不能再修改它的大小

//创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值
数据类型[] 数组名 = new 数据类型[长度]; 
//创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤的!
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,...,数据n};
数据类型[] 数组名 = {数据1,数据2,...,数据n};

数组定义以及初始化:

int []s={2,3};
        int a[]={3,2};
        int [][]arg1={{1,2},{3,4}};
        int arg2[][]={{1,2},{3,4}};
        int []arg3[]={{1,2},{3,4}};
        //变量名位置不影响

        int arg4[][]=new int[5][];
        int arg5[]=new int[]{2};
        int arg6[][]={{},{}};//定义不赋值
        int arg7[][]=new int[][]{{1},{1,2},{9}};//定义且赋初值
        System.out.println(arg7.length+","+arg7[0].length+","+arg7[1].length+","+arg7[2].length);//3,1,2,1
        int arg8[][]=new int[][]{{100,200,300,400},{500,600,700,800},{900,1000,1100,1200,1300}};//定义且赋初值
        int [][]atg9=new int[3][];//可只定义行不定义列

6.2 常用数组操作

数组遍历问题

数组元素可以通过下标访问。

数组下标是基于 0的,也就是说,其范围从 0 开时直到array.length - 1结束

for循环通过下标遍历

public class Sor {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
        //String str str.length()-调用length函数获取srt的大小
        //int[] arr arr.length-这是arr的数组长度,是属性
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * 10;
            System.out.println(arr[i]);
        }
        //通过角标遍历 可以在遍历的过程中对指定的元素进行修改
    }
}

foreach遍历(不使用下标)

public class Sor {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
        //foreach遍历 主要针对的是一些可迭代对象 Iterable
        /*
        for (数据类型 变量名 : 可迭代容器) {
        }
        */
        for (int num : arr) {
            //num -> arr[i]
            num = num / 10;
            System.out.println(num);
        }
        //这种遍历方式 只能获取元素,不能修改元素
    }
}

数组扩容问题

数组本身大小不能被改变,但是往数组中添加元素可以进行,

在堆中创建新的数组比原数组长度增加一个,

再遍历原数组,将原来的数据赋值到新数组,再将要添加的数据放入增加的空间中

最后让数组的地址指向新数组,这就完成了数组的扩容

public class Sor {
    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(", ");
			}
		}
	}
}

二分查找算法

二分查找法前提是有序数组
思路: 在有序数组(这里默认升序)中,每次找到最小值,最大值,中间值,
比较中间值和当前寻找值的大小,大于则在有序数组的右边,重新赋值最大值,最小值,
一直重复直到找到元素,返回下标
如果当最小值的下标大于最大值的下标时表示没找到返回-1.

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

计数排序:

解:
计数排序就是 把每个数出现的次数值 放入 标有和它一样数字的容器,一般采用数组来作为存这些数出现次数的容器。容器的标号就是数组的下标。排序时只需要顺序遍历一遍容器,把 有数据的容器 输出下标 数据中 下标值出现次数 次。
排序的数据为:2 - 1 1 2 3 6 2 6
我们根据数据的最大值,需要开一个数组int c[7],这样我们就有了容器c[0] ,c[1] ,c[2], c[3],c[4],c[5],c[6],c[7];计数之前令每个容器的初值为 0;
把 每个数的 出现次数 放入对应标号容器:
c[0] = 1;
c[2] = 1;
c[3] = 3;
c[4] = 1;
c[7] = 2;

在这里插入图片描述

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(", ");
			}
		}
	}
}

6.2 二维数组

二维数组:二维数组就是存储一维数组(内存地址/引用)的数组
在这里插入图片描述

二维数组的定义

  1. int[][] intA={{1,2},{2,3},{3,4,5}};

  2. int[][] intB=new int[3][5];

public class TestArray {
    public static void main(String[] args) {
        int[][] A ={{1,2},{2,3,4},{3,4,5,6}};
		int[][] B = new int[3][4];
		
		//二维数组不是规则的矩阵
        int[][] C = {
        {1},
        {1,2,3},
        {1,2,3,4},
        {7,6,5,4,3,2,1}};
    }
}

案例1
输入8个点坐标,然后计算这些点中,那两个点的距离是最近的?
解: 定义一个二维数组,来接受用户输入的八个点的坐标,
在循环判断两个坐标的距离,从而获取两点间的最短距离。

import java.util.Scanner;
public class Sample {
	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++) {
			System.out.print("请输入第" + (i + 1) + "个点坐标:");
			points[i][0] = input.nextDouble();
			points[i][1] = input.nextDouble();
		}
		//默认最短距离为点0和点1
		double shortestDistance = getDistance(points,0,1);
		int p1 = 0;
		int p2 = 1;
		for (int i = 0; i < points.length - 1; i++) {
			for (int j = i + 1; j < points.length; j++) {
				double distance = getDistance(points,i,j);
				//比较判断最短距离,小于就获取该下标
				if (distance < shortestDistance) {
					shortestDistance = 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],shortestDistance);
	}
		public static double getDistance(double[][] m , int p1 , int p2) {
			//计算两点间的距离
			return Math.hypot(m[p1][0] - m[p2][0] , m[p1][1] - m[p2][1]);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值