数组的常用操作
一、学习目标
①理解数组
②熟练使用一维数组解决实际问题(重点)
③使用数组实现常用算法(难点)
④掌握二维数组的使用
二、数组概述
2.1 概念
数组是一个变量,由数据类型相同的一组元素组成。是内存中一串连续的空间。
2.2 数组的结构和基本要素
①标识符:数组的名称,用于区分不同的数组
②数组元素:向数组中存放的数据
③元素下标:对数组元素进行编号
④元素类型:数组元素的数据类型
2.3 数组特点
①数组下标从0开始
②数组元素可以通过下标访问
③数组长度固定不变,避免数组越界
三、数组的使用
3.1 一维数组
语法:
datatype[] arrayName = new datatype[size]; //例 int[] nums; String[] names = new String[15]; double[] salarys = new double[55];
一维数组的初始化:
//声明的同时初始化 datatype[] arrayName = {data1,data2,data3,...}; datatype[] arrayName = new datatype[]{data1,data2,data3,...}; //错误:声明初始化数组是不需要指定数组的大小 int years[6] = {2012,2013,2014,2015,2016,2017}; //错误:声明并初始化数是不需要指定数组的大小 int[12] months = {1,3,5,7,9,11}; //正确:元素个数为2(days.length == 2) int days[] = {1,15}; //正确: int array[] = {};
数组长度和默认值:
①创建数组后就不能再修改数组的代销
②基本数据类型数组的默认值为0
③char型数组元素的默认值为/u0000
④布尔类型数组的默认值为false
⑤引用类型数组的默认值为null
数组的应用实例:
需求:
1.求数组中的最大值和最小值
2.定义一个整型数组,赋值后求出奇数个数和偶数个数
3.查找输入的数字咋数组中的下标,没有找到则下标为-1
4.随机打乱数组中的元素顺序
5.使用foreach简化数组的遍历
6.数组的复制
3.2 二维数组
语法:
datatype[][] names; double[][] scores new double[5][3]; int[][] animates; animates new int[4][4];
二维数组的动态赋值:
String stuNames = {"刘备", "关羽", "张飞"}; String courseNames = {"语文", "数学", "英语"}; final int ROW = stuNames.length; final int COL = courseNames.length; double[][] scores = new double[ROW][COL]; for(int i = 0; i < ROW; i++){ for(int j = 0; j < COL; j++){ System.out.print(stuNames[i] + "的" + courseNames[j] + "成绩"); scores[i][j] = new Scanner(System.in).nextDouble(); } }
四、数组排序
4.1 冒泡排序
原理:
//对于一个乱序的数组,进行冒泡排序,升序排序 {18,9,1,2,7} //第一轮比较 {18,9,1,2,7} //首先拿第一个元素18与后一个元素9进行比较,18>9,进行交换,数组变成 {9,18,1,2,7} //然后拿第二个元素18与后一个元素1进行比较,18>1,进行交换,数组变成 {9,1,18,2,7} //然后拿第三个元素18与后一个元素2进行比较,18>2,进行交换,数组变成 {9,1,2,18,7} //然后拿第四个元素18与后一个元素7进行比较,18>7,进行交换,数组变成 {9,1,2,7,18} //第一轮比较结束后,最大的18移动到了数组的末尾,一共进行了4次比较 //第二轮比较 {9,1,2,7,18} //首先拿第一个元素9与后一个1进行比较,9>1,进行交换,数组变成 {1,9,2,7,18} //然后拿第二个元素9与后一个2进行比较,9>2,进行交换,数组变成 {1,2,9,7,18} //然后拿第三个元素9与后一个7进行比较,9>7,进行交换,数组变成 {1,2,7,9,18} //由于后一位18经上一轮比较已确定为最大数,所以9不用与18进行比较 //经过第二轮比较,第二大的9移动到了数组的倒数第二位,一共进行了3次比较 //第三轮比较 {1,2,7,9,18} //首先拿第一个元素1与后一个2进行比较,1<2,不进行交换,数组变成 {1,2,7,9,18} //然后拿第二个元素2与后一个7进行比较,2<7,不进行交换,数组变成 {1,2,7,9,18} //由于后一位9经上一轮比较,已经确定了位置,所以,7不用与9进行比较 //经过第三轮比较,第三大的7移动到了数组的倒数第三位,一共进行了2次比较 //第四轮比较 {1,2,7,9,18} //首先拿第一个元素与后一个2进行比较,1<2,不进行交换 //由于第三个元素位置已经在上一轮中确认,所以不用拿第2个元素和第三个元素比较 //本轮一共进行了1次比较。 //到此为止,冒泡排序结束。 //根据上述操作,可以得出一些冒泡排序的基本规律(读者可以用其他长度的数组进行试验证明): //1、冒泡排序的总的排序轮数,为数组的元素个数-1,即数组长度length - 1(即n个数,每次确定一个数的位置,只用比较n-1次就能确定完所有数的位置,最后一次只剩一个数,没有必要比较); //2、冒泡排序每轮排序执行的总的比较操作次数j为数组元素个数减去1再减去当前轮数(因为每比较一轮,就确定一个数的位置,就代表下一轮少比较一个数),即每轮排序执行的总的比较次数为 //length - 1 - 当前轮数; //3、每一轮比较中,比较的两个元素为第j个元素和第j + 1个元素,其中j为当前比较的次数,即第一次比较第1个元素和第2个元素,第二次比 //较第2个元素和第3个元素,第三次比较第3个元素和第4个元素
代码:
//根据上述规律,可以写出代码 int[] nums = {18,9,1,2,7}; for(int i = 0; i < length - 1; i++){//用于控制执行排序的轮数,由规律1可知,最多执行length - 1次,因为从0开始,所以是<符号 for(int j = 0; j < length - i - 1; j++){//用于控制当前轮数的排序次数,由规律2可知,最多执行length - i(当前轮数) - 1次。 if(nums[j] > nums[j + 1]){//如果当前元素大于后一个元素,则将两个元素进行交换 int temp = nums[j]; nums[j] = nums[j + 1]; nums[j + 1] = temp; } } } //上述代码即为冒泡排序的完整代码,如果要进行降序排序,只需将if处的>符号替换为<符号即可。
4.2 选择排序
代码区别:
①选择排序的代码有两种情况,一种是从后往前排,即升序排序,每次找出剩余元素的最大值或者降序排序,每次找出剩余元素的最小值。
②另一种是从前往后排,即升序排序,每次找出剩余元素的最小值或者降序排序,每次找出剩余元素的最大值)
原理:
假设以升序排序,每次找出数组中剩余元素的最大值。
①首先,声明一个变量存储最大值下标,每轮查找先将下标更新为数组第一个元素。
②然后将拿数组中的所有元素依次和最大值进行比较。
③在比较过程中如果有某个值比最大值大时,将最大值下标更新为该处元素的下标。然后继续进行后续比较。
④进行过一轮比较后,确定首轮中元素的最大值下标,然后将最大值下标除的元素与数组最后一个元素进行交换。
⑤进行第二轮比较时,先将最大值下标更新为数组第一个元素下标,即0,再进行比较,此时由于最后一位已确定,所以比较次数较第一轮比较少一次。
代码实现:
int[] nums = {18,9,1,2,7}; int maxIndex; //外层循环控制排序轮数 for(int i = 0; i < nums.length - 1; i++){ //每次新轮数,将最大值下标更新为0 maxIndex = 0; //内存循环控制每轮排序次数 for(int j = 0; j < nums.length - i; j ++){ if(nums[j] > nums[maxIndex]){ maxIndex = j; } } //查找完毕后,将最大值与数组最后一个未确定的元素进行交换 int temp = nums[maxIndex]; nums[maxIndex] = nums[nums.length - 1 - i]; nums[nums.length - 1 - i] = temp; }