数组
1、数组的概述
1 为什么需要数组
需求分析:
需要统计某公司50个员工的工资情况,例如计算平均工资、找到最高工资等。用之前知识,首先需要声明50个变量
来分别记录每位员工的工资,这样会很麻烦。因此我们可以将所有的数据全部存储到一个容器中统一管理,并使用容器进行计算。
容器的概念:
-
生活中的容器:水杯(装水等液体),衣柜(装衣服等物品),集装箱(装货物等)。
-
程序中的容器:将多个数据存储到一起,每个数据称为该容器的元素。
2 数组的概念
-
数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
-
数组中的概念
-
数组名
-
下标(或索引)
-
元素
-
数组的长度
-
数组的特点:
-
数组本身是
引用数据类型
,而数组中的元素可以是任何数据类型
,包括基本数据类型和引用数据类型。 -
创建数组对象会在内存中开辟一整块
连续的空间
。占据的空间的大小,取决于数组的长度和数组中元素的类型。 -
数组中的元素在内存中是依次紧密排列的,有序的。
-
数组,一旦初始化完成,其长度就是确定的。数组的
长度一旦确定,就不能修改
。 -
我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
-
数组名中引用的是这块连续空间的首地址。
3 数组的分类
1、按照元素类型分:
-
基本数据类型元素的数组:每个元素位置存储基本数据类型的值
-
引用数据类型元素的数组:每个元素位置存储对象(本质是存储对象的首地址)(在面向对象部分讲解)
2、按照维度分:
-
一维数组:存储一组数据
-
二维数组:存储多组数据,相当于二维表,一行代表一组数据,只是这里的二维表每一行长度不要求一样。
2、一维数组
1,数组的理解(Array)
概念:是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
简称:多个数据的组合
Java中的容器:数组、集合框架:在内存中对多个数据的存储。
2,几个相关的概念
数组名 数组的元素(即内部存储的多个元素) 数组的下标、角标、下角标、索引、index(即找到指定数组元素所使用的编号) 数组的长度(即数组容器中存储的元素的个数)
3,数组的特点:
数组中的元素在内存中是依次紧密排列的,有序的。 数组,属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以引用数据类型。 数组,一旦初始化完成,其长度就确定了,并且其长度不可更改。 创建数组对象会在内存中开辟一整块连续的空间
。占据的空间的大小,取决于数组的长度和数组中元素的类型。
4,复习:变量按照数据类型的分类
4.1 基本数据类型:byte \ short \ int \ long ;float \ double ; char \ boolean 4.2 引用数据类型:类、数组、接口、枚举、注解、记录
5,数组的分类
5.1 按照元素的类型:基本数据类型元素的数组;引用数据类型元素的数组 5.2 按照数组的维数来分:一维数组;二维数组;.....
6,一维数组的使用(6个基本点)
数组的声明和初始化
1 一维数组的声明
格式:
//推荐 元素的数据类型[] 一维数组的名称; //不推荐 元素的数据类型 一维数组名[];
举例:
int[] arr; int arr1[]; double[] arr2; String[] arr3; //引用类型变量数组
数组的声明,需要明确:
(1)数组的维度:在Java中数组的符号是[],[]表示一维,[][]表示二维。
(2)数组的元素类型:即创建的数组容器可以存储什么数据类型的数据。元素的类型可以是任意的Java的数据类型。例如:int、String、Student等。
(3)数组名:就是代表某个数组的标识符,数组名其实也是变量名,按照变量的命名规范来命名。数组名是个引用数据类型的变量,因为它代表一组数据。
注意:Java语言中声明数组时不能指定其长度(数组中元素的个数)。 例如: int a[5]; //非法
2 一维数组的初始化
静态初始化
如果数组变量的初始化和数组元素的赋值操作同时进行,那就称为静态初始化。
静态初始化,本质是用静态数据(编译时已知)为数组初始化。此时数组的长度由静态数据的个数决定。
-
一维数组声明和静态初始化格式1:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,...}; 或 数据类型[] 数组名; 数组名 = new 数据类型[]{元素1,元素2,元素3,...};
-
new:关键字,创建数组使用的关键字。因为数组本身是引用数据类型,所以要用new创建数组实体。
例如,定义存储1,2,3,4,5整数的数组容器。
int[] arr = new int[]{1,2,3,4,5};//正确 //或 int[] arr; arr = new int[]{1,2,3,4,5};//正确
-
一维数组声明和静态初始化格式2:
数据类型[] 数组名 = {元素1,元素2,元素3...};//必须在一个语句中完成,不能分成两个语句写
例如,定义存储1,2,3,4,5整数的数组容器
int[] arr = {1,2,3,4,5};//正确 int[] arr; arr = {1,2,3,4,5};//错误
动态初始化
数组变量的初始化和数组元素的赋值操作分开进行,即为动态初始化。
动态初始化中,只确定了元素的个数(即数组的长度),而元素值此时只是默认值,还并未真正赋自己期望的值。真正期望的数据需要后续单独一个一个赋值。
格式:
数组存储的元素的数据类型[] 数组名字 = new 数组存储的元素的数据类型[长度]; 或 数组存储的数据类型[] 数组名字; 数组名字 = new 数组存储的数据类型[长度];
-
[长度]:数组的长度,表示数组容器中可以最多存储多少个元素。
-
注意:数组有定长特性,长度一旦指定,不可更改。和水杯道理相同,买了一个2升的水杯,总容量就是2升是固定的。
调用数组的指定元素
如何表示数组中的一个元素?
每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index)或下标
,可以通过数组的索引/下标访问到数组中的元素。
数组名[索引/下标]
数组的下标范围?
Java中数组的下标从[0]开始,下标范围是[0, 数组的长度-1],即[0, 数组名.length-1]
数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];
数组的属性:length,表示数组的长度
-
数组的元素总个数,即数组的长度
-
每个数组都有一个属性length指明它的长度,例如:arr.length 指明数组arr的长度(即元素个数)
-
每个数组都具有长度,而且一旦初始化,其长度就是确定,且是不可变的。
数组的遍历
将数组中的每个元素分别获取出来,就是遍历
。for循环与数组的遍历是绝配。
举例
public class ArrayTest4 { public static void main(String[] args) { int[] arr = new int[]{1,2,3,4,5}; //打印数组的属性,输出结果是5 System.out.println("数组的长度:" + arr.length); //遍历输出数组中的元素 System.out.println("数组的元素有:"); for(int i=0; i<arr.length; i++){ System.out.println(arr[i]); } } }
数组元素的默认初始化值
注意:以数组的动态初始化方式为例说明。
数组是引用类型,当我们使用动态初始化方式创建数组时,元素值只是默认值。例如:
public class ArrayTest6 { public static void main(String argv[]){ int a[]= new int[5]; System.out.println(a[3]); //a[3]的默认值为0 } }
对于基本数据类型而言,默认初始化值各有不同。
对于引用数据类型而言,默认初始化值为null(注意与0不同!)
数组元素类型 | 元素默认初始值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0F |
double | 0.0 |
char | 0或写为:'\u0000'(表现为空) |
boolean | false |
引用类型 | null |
一维数组的内存解析(难)
1. Java虚拟机的内存划分
将内存区域划分为5个部分:程序计数器、虚拟机栈、本地方法栈、堆、方法区
与目前数组相关的内存结构: 比如:int[] arr = new int[]{1,2,3}; 虚拟机栈:用于存放方法中声明的变量。比如:arr 堆:用于存放数组的实体(即数组中的所有元素)。比如:1,2,3
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
区域名称 | 作用 |
---|---|
虚拟机栈 | 用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度 的各种基本数据类型、对象引用,方法执行完,自动释放。 |
堆内存 | 存储对象(包括数组对象),new来创建的,都存储在堆内存。 |
方法区 | 存储已被虚拟机加载的类信息、常量、(静态变量)、即时编译器编译后的代码等数据。 |
本地方法栈 | 当程序中调用了native的本地方法时,本地方法执行期间的内存区域 |
程序计数器 | 程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址 |
2.数组下标为什么是0开始
因为第一个元素距离数组首地址间隔0个单元格。
2、二维数组
1.二维数组的理解
-
对于二维数组的理解,可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。
-
其实,从数组底层的运行机制来看,其实没有多维数组。
-
概念:数组的外层元素;数组的内层元素
2.二维数组的使用(6个基本点)
数组的声明和初始化
1.声明
二维数组声明的语法格式:
//推荐 元素的数据类型[][] 二维数组的名称; //不推荐 元素的数据类型 二维数组名[][]; //不推荐 元素的数据类型[] 二维数组名[];
2. 静态初始化
格式:
int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
定义一个名称为arr的二维数组,二维数组中有三个一维数组
-
每一个一维数组中具体元素也都已初始化
-
第一个一维数组 arr[0] = {3,8,2};
-
第二个一维数组 arr[1] = {2,7};
-
第三个一维数组 arr[2] = {9,0,1,6};
-
-
第三个一维数组的长度表示方式:arr[2].length;
-
注意特殊写法情况:int[] x,y[]; x是一维数组,y是二维数组。
-
举例:
int[][] arr = {{1,2,3},{4,5,6},{7,8,9,10}};//声明与初始化必须在一句完成 int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}}; int[][] arr; arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}}; arr = new int[3][3]{{1,2,3},{4,5,6},{7,8,9,10}};//错误,静态初始化右边new 数据类型[][]中不能写数字
3 .动态初始化
如果二维数组的每一个数据,甚至是每一行的列数,需要后期单独确定,那么就只能使用动态初始化方式了。动态初始化方式分为两种格式:
格式1:规则二维表:每一行的列数是相同的
//(1)确定行数和列数 元素的数据类型[][] 二维数组名 = new 元素的数据类型[m][n]; //其中,m:表示这个二维数组有多少个一维数组。或者说一共二维表有几行 //其中,n:表示每一个一维数组的元素有多少个。或者说每一行共有一个单元格 //此时创建完数组,行数、列数确定,而且元素也都有默认值 //(2)再为元素赋新值 二维数组名[行下标][列下标] = 值;
举例:
int[][] arr = new int[3][2];
-
定义了名称为arr的二维数组
-
二维数组中有3个一维数组
-
每一个一维数组中有2个元素
-
一维数组的名称分别为arr[0], arr[1], arr[2]
-
给第一个一维数组1脚标位赋值为78写法是:
arr[0][1] = 78;
格式2:不规则:每一行的列数不一样
//(1)先确定总行数 元素的数据类型[][] 二维数组名 = new 元素的数据类型[总行数][]; //此时只是确定了总行数,每一行里面现在是null //(2)再确定每一行的列数,创建每一行的一维数组 二维数组名[行下标] = new 元素的数据类型[该行的总列数]; //此时已经new完的行的元素就有默认值了,没有new的行还是null //(3)再为元素赋值 二维数组名[行下标][列下标] = 值;
举例:
int[][] arr = new int[3][];
-
二维数组中有3个一维数组。
-
每个一维数组都是默认初始化值null (注意:区别于格式1)
-
可以对这个三个一维数组分别进行初始化:arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2];
-
注:
int[][]arr = new int[][3];
//非法
调用数组的指定元素
同一维数组
数组的属性:length,表示数组的长度
-
二维数组的长度/行数:二维数组名.length
-
二维数组的某一行:二维数组名[行下标],此时相当于获取其中一组数据。它本质上是一个一维数组。行下标的范围:[0, 二维数组名.length-1]。此时把二维数组看成一维数组的话,元素是行对象。
-
某一行的列数:二维数组名[行下标].length,因为二维数组的每一行是一个一维数组。
-
某一个元素:二维数组名[行下标][列下标],即先确定行/组,再确定列。
数组的遍历
格式:
for(int i=0; i<二维数组名.length; i++){ //二维数组对象.length for(int j=0; j<二维数组名[i].length; j++){//二维数组行对象.length System.out.print(二维数组名[i][j]); } System.out.println(); }
数组元素的默认初始化值
1 动态初始化方式1:(比如:int arr = new int3)
1)外层元素,默认存储地址值。 2)内层元素,默认与一维数组元素的不同类型的默认值规定相同。 > 整型数组元素的默认初始化值:0 > 浮点型数组元素的默认初始化值:0.0 > 字符型数组元素的默认初始化值:0 (或理解为'\u0000') > boolean型数组元素的默认初始化值:false > 引用数据类型数组元素的默认初始化值:null
2 动态初始化方式2:(比如:int arr = new int3) 1)外层元素,默认存储null 2)内层元素,不存在的。如果调用会报错(NullPointerException)
二维数组的内存解析(难)
二维数组本质上是元素类型是一维数组的一维数组。
3、 数组的常见算法
1 数值型数组特征值统计
这里的特征值涉及到:平均值、最大值、最小值、总和等
举例1:数组统计:求总和、均值
public class TestArrayElementSum { public static void main(String[] args) { int[] arr = {4,5,6,1,9}; //求总和、均值 int sum = 0;//因为0加上任何数都不影响结果 for(int i=0; i<arr.length; i++){ sum += arr[i]; } double avg = (double)sum/arr.length; System.out.println("sum = " + sum); System.out.println("avg = " + avg); } }
举例2:求数组元素的总乘积
public class TestArrayElementMul { public static void main(String[] args) { int[] arr = {4,5,6,1,9}; //求总乘积 long result = 1;//因为1乘以任何数都不影响结果 for(int i=0; i<arr.length; i++){ result *= arr[i]; } System.out.println("result = " + result); } }
举例3:求数组元素中偶数的个数
public class TestArrayElementEvenCount { public static void main(String[] args) { int[] arr = {4,5,6,1,9}; //统计偶数个数 int evenCount = 0; for(int i=0; i<arr.length; i++){ if(arr[i]%2==0){ evenCount++; } } System.out.println("evenCount = " + evenCount); } }
举例4:求数组元素的最大值
public class TestArrayMax { public static void main(String[] args) { int[] arr = {4,5,6,1,9}; //找最大值 int max = arr[0]; for(int i=1; i<arr.length; i++){//此处i从1开始,是max不需要与arr[0]再比较一次了 if(arr[i] > max){ max = arr[i]; } } System.out.println("max = " + max); } }
举例5:找最值及其第一次出现的下标
public class TestMaxIndex { public static void main(String[] args) { int[] arr = {4,5,6,1,9}; //找最大值以及第一个最大值下标 int max = arr[0]; int index = 0; for(int i=1; i<arr.length; i++){ if(arr[i] > max){ max = arr[i]; index = i; } } System.out.println("max = " + max); System.out.println("index = " + index); } }
举例6:找最值及其所有最值的下标
public class Test13AllMaxIndex { public static void main(String[] args) { int[] arr = {4,5,6,1,9,9,3}; //找最大值 int max = arr[0]; for(int i=1; i<arr.length; i++){ if(arr[i] > max){ max = arr[i]; } } System.out.println("最大值是:" + max); System.out.print("最大值的下标有:"); //遍历数组,看哪些元素和最大值是一样的 for(int i=0; i<arr.length; i++){ if(max == arr[i]){ System.out.print(i+"\t"); } } System.out.println(); } }
优化
public class Test13AllMaxIndex2 { public static void main(String[] args) { int[] arr = {4,5,6,1,9,9,3}; //找最大值 int max = arr[0]; String index = "0"; for(int i=1; i<arr.length; i++){ if(arr[i] > max){ max = arr[i]; index = i + ""; }else if(arr[i] == max){ index += "," + i; } } System.out.println("最大值是" + max); System.out.println("最大值的下标是[" + index+"]"); } }
举例7(难):输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如:输入的数组为1, -2, 3, -10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
public class Test5 { public static void main(String[] args) { int[] arr = new int[]{1, -2, 3, 10, -4, 7, 2, -5}; int i = getGreatestSum(arr); System.out.println(i); } public static int getGreatestSum(int[] arr){ int greatestSum = 0; if(arr == null || arr.length == 0){ return 0; } int temp = greatestSum; for(int i = 0;i < arr.length;i++){ temp += arr[i]; if(temp < 0){ temp = 0; } if(temp > greatestSum){ greatestSum = temp; } } if(greatestSum == 0){ greatestSum = arr[0]; for(int i = 1;i < arr.length;i++){ if(greatestSum < arr[i]){ greatestSum = arr[i]; } } } return greatestSum; } }
举例8:评委打分
分析以下需求,并用代码实现:
(1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3
(2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)
public class ArrayExer { public static void main(String[] args) { int[] scores = {5,4,6,8,9,0,1,2,7,3}; int max = scores[0]; int min = scores[0]; int sum = 0; for(int i = 0;i < scores.length;i++){ if(max < scores[i]){ max = scores[i]; } if(min > scores[i]){ min = scores[i]; } sum += scores[i]; } double avg = (double)(sum - max - min) / (scores.length - 2); System.out.println("选手去掉最高分和最低分之后的平均分为:" + avg); } }
2 数组元素的反转
实现思想:数组对称位置的元素互换。
public class TestArrayReverse1 { public static void main(String[] args) { int[] arr = {1,2,3,4,5}; System.out.println("反转之前:"); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } //反转 /* 思路:首尾对应位置的元素交换 (1)确定交换几次 次数 = 数组.length / 2 (2)谁和谁交换 for(int i=0; i<次数; i++){ int temp = arr[i]; arr[i] = arr[arr.length-1-i]; arr[arr.length-1-i] = temp; } */ for(int i=0; i<arr.length/2; i++){ int temp = arr[i]; arr[i] = arr[arr.length-1-i]; arr[arr.length-1-i] = temp; } System.out.println("反转之后:"); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
或
public class TestArrayReverse2 { public static void main(String[] args) { int[] arr = {1,2,3,4,5}; System.out.println("反转之前:"); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } //反转 //左右对称位置交换 for(int left=0,right=arr.length-1; left<right; left++,right--){ //首 与 尾交换 int temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; } System.out.println("反转之后:"); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
3 数组的扩容与缩容
数组的扩容
题目:现有数组 int[] arr = new int[]{1,2,3,4,5}; ,现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?
public class ArrTest1 { public static void main(String[] args) { int[] arr = new int[]{1,2,3,4,5}; int[] newArr = new int[arr.length << 1]; for(int i = 0;i < arr.length;i++){ newArr[i] = arr[i]; } newArr[arr.length] = 10; newArr[arr.length + 1] = 20; newArr[arr.length + 2] = 30; arr = newArr; //遍历arr for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
数组的缩容
题目:现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。
public class ArrTest2 { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5, 6, 7}; //删除数组中索引为4的元素 int delIndex = 4; //方案1: /*//创建新数组 int[] newArr = new int[arr.length - 1]; for (int i = 0; i < delIndex; i++) { newArr[i] = arr[i]; } for (int i = delIndex + 1; i < arr.length; i++) { newArr[i - 1] = arr[i]; } arr = newArr; for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); }*/ //方案2: for (int i = delIndex; i < arr.length - 1; i++) { arr[i] = arr[i + 1]; } arr[arr.length - 1] = 0; for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
4 数组的元素查找
1、顺序查找
顺序查找:挨个查看
要求:对数组元素的顺序没要求
public class TestArrayOrderSearch { //查找value第一次在数组中出现的index public static void main(String[] args){ int[] arr = {4,5,6,1,9}; int value = 1; int index = -1; for(int i=0; i<arr.length; i++){ if(arr[i] == value){ index = i; break; } } if(index==-1){ System.out.println(value + "不存在"); }else{ System.out.println(value + "的下标是" + index); } } }
2、二分查找
举例:
//二分法查找:要求此数组必须是有序的。 int[] arr3 = new int[]{-99,-54,-2,0,2,33,43,256,999}; boolean isFlag = true; int value = 256; //int value = 25; int head = 0;//首索引位置 int end = arr3.length - 1;//尾索引位置 while(head <= end){ int middle = (head + end) / 2; if(arr3[middle] == value){ System.out.println("找到指定的元素,索引为:" + middle); isFlag = false; break; }else if(arr3[middle] > value){ end = middle - 1; }else{//arr3[middle] < value head = middle + 1; } } if(isFlag){ System.out.println("未找打指定的元素"); }
5 数组元素排序
1 算法概述
-
定义
-
排序:假设含有n个记录的序列为{R1,R2,...,Rn},其相应的关键字序列为{K1,K2,...,Kn}。将这些记录重新排序为{Ri1,Ri2,...,Rin},使得相应的关键字值满足条Ki1<=Ki2<=...<=Kin,这样的一种操作称为排序。
-
通常来说,排序的目的是快速查找。
-
-
衡量排序算法的优劣:
-
时间复杂度
:分析关键字的比较次数和记录的移动次数 -
常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)<O(nn)
-
空间复杂度
:分析排序算法中需要多少辅助内存一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。
-
稳定性
:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。
-
2 排序算法概述
-
排序算法分类:内部排序和外部排序
-
内部排序
:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。 -
外部排序
:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。
-
-
十大内部排序算法
数组的排序算法很多,实现方式各不相同,时间复杂度、空间复杂度、稳定性也各不相同:
常见时间复杂度所消耗的时间从小到大排序:
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
注意,经常将以2为底n的对数简写成logn。
3 冒泡排序(Bubble Sort)
排序思想:
-
比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
-
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止。
动态演示:排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,计数排序,基数排序) - VisuAlgo
4、Arrays工具类的使用
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。 比如:
-
数组元素拼接`
-
static String toString(int[] a) :字符串表示形式由数组的元素列表组成,括在方括号("[]")中。相邻元素用字符 ", "(逗号加空格)分隔。形式为:[元素1,元素2,元素3。。。]
-
static String toString(Object[] a) :字符串表示形式由数组的元素列表组成,括在方括号("[]")中。相邻元素用字符 ", "(逗号加空格)分隔。元素将自动调用自己从Object继承的toString方法将对象转为字符串进行拼接,如果没有重写,则返回类型@hash值,如果重写则按重写返回的字符串进行拼接。
-
-
数组排序
-
static void sort(int[] a) :将a数组按照从小到大进行排序
-
static void sort(int[] a, int fromIndex, int toIndex) :将a数组的[fromIndex, toIndex)部分按照升序排列
-
static void sort(Object[] a) :根据元素的自然顺序对指定对象数组按升序进行排序。
-
static <T> void sort(T[] a, Comparator<? super T> c) :根据指定比较器产生的顺序对指定对象数组进行排序。
-
-
数组元素的二分查找
-
static int binarySearch(int[] a, int key) 、static int binarySearch(Object[] a, Object key) :要求数组有序,在数组中查找key是否存在,如果存在返回第一次找到的下标,不存在返回负数。
-
-
数组的复制
-
static int[] copyOf(int[] original, int newLength) :根据original原数组复制一个长度为newLength的新数组,并返回新数组
-
static <T> T[] copyOf(T[] original,int newLength):根据original原数组复制一个长度为newLength的新数组,并返回新数组
-
static int[] copyOfRange(int[] original, int from, int to) :复制original原数组的[from,to)构成新数组,并返回新数组
-
static <T> T[] copyOfRange(T[] original,int from,int to):复制original原数组的[from,to)构成新数组,并返回新数组
-
-
比较两个数组是否相等
-
static boolean equals(int[] a, int[] a2) :比较两个数组的长度、元素是否完全相同
-
static boolean equals(Object[] a,Object[] a2):比较两个数组的长度、元素是否完全相同
-
-
填充数组
-
static void fill(int[] a, int val) :用val值填充整个a数组
-
static void fill(Object[] a,Object val):用val对象填充整个a数组
-
static void fill(int[] a, int fromIndex, int toIndex, int val):将a数组[fromIndex,toIndex)部分填充为val值
-
static void fill(Object[] a, int fromIndex, int toIndex, Object val) :将a数组[fromIndex,toIndex)部分填充为val对象
-