目录
数组的概述
数组 (Array),是多个相同类型数据按一定顺序排列的集合 ,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理 。
数组的常见概念
数组名
下标 (或索引 )
元素
数组的长度
数组本身是引用数据类型,而数组中的元素可以是任何数据类型 ,包括基本数据类型和引用数据类型。
创建数组对象会在内存中开辟一整块连续的空间 ,而数组名中引用的是这块连续空间的首地址 。
数组的长度一旦确定,就不能修改 。
我们可以直接通过下标 (或索引 )的方式调用指定位置元素 ,速度很快 。
数组的分类:
按照维度:一维数组、二维数组、三维数组 、…
按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组 )
一维数组的使用
声明
一维数组的声明方式:
type var[] 或 type[] var ;
例如:
int a[] ;
int[] a1;
double b[] ;
String[] c;// 引用类型变量数组
Java 语言中声明数组时不能指定其长度 (数组中元素的个数), 例如: int a[5 ]; // 非法
初始化
动态初始化:数组声明且为元素分配空间,与赋值的操作分开进行
int[] arr = new int[3];
arr[0] = 3;
arr[1] = 4;
arr[2] = 5;
String names[];
names = new String[3];
names[0] = “钱学森”;
names[1] = “邓稼先”;
names[2] = “袁隆平”;
静态初始化:在定义数组的同时就为数组元素分配空间并赋值
int arr[] = new int[]{3,4,5};
或
int[] arr = {3,4,5};
String names[] = {"李四光","茅以升","华罗庚"}
数组元素的引用
定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;
数组元素的引用方式:数组名[数组元素下标]
数组元素下标可以是整型常量或表达式。如 a[3],b[i] , c[6* ],c[6*i];
数组元素下标从0开始;长度为n的数组合法下标取值范围 : 0—>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]、a[1]、a[2]
每个数组都有一个属性length指明它的长度,例如:a.length指明数组a的长度(元素个数 )
数组一旦初始化,其长度是不可变的
遍历数组
for (int i =0;i < arr.length;i++){
}
数组元素的默认初始化值
数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化
对于基本数据类型而言,默认初始化值各有不同。整型0,浮点型0.0,char型0或‘\u0000’(表现效果为空),boolean型false
对于引用数据类型而言,默认初始化值为null(注意与0不同!)
数组的内存解析
创建基本数据类型数组
public class Test {
public static void main(String[] args) {
int[] s;
s = new int[10];
for (int i = 0;i<s.length;i++) {
s[i] = 2*i+1;
System.out.println(s[i]);
}
}
}
int[] s | s = new int[10] | s[i]=2*i+1 |
| ![]() | ![]() |
内存结构简化
main方法中局部变量ages存放在栈里,ages指向在堆中开辟的空间
练习
从键盘读入学生成绩, 找出最高分并输出学生成绩等级。
成绩 >= 最高分-10 等级为 ’A’
成绩 >= 最高分-20 等级为 ’B’
成绩 >= 最高分-30 等级为 ’C’
其余 等级为’D’
提示:先读入学生人数,根据人数创建 int数组, 存放学生成绩。
public class Score {
public static void main(String[] args) {
//使用scanner读取学生个数
System.out.print("输入学生人数:");
Scanner scan =new Scanner(System.in);
int n = scan.nextInt();
//创建数组存储学生成绩,动态初始化
//给数组中的元素赋值
double[] score = new double[n];
for(int i =0;i<n;i++) {
System.out.println("输入第"+(i+1)+"个学生分数:");
score[i] = scan.nextDouble();
}
//获取数组中的最大值
double maxScore = score[0];
for(int i =0;i<n;i++) {
if(score[i]>maxScore)
maxScore = score[i];
}
System.out.println("最高分是"+maxScore);
char level;
for (int i=0;i<n;i++) {
if(score[i]>=maxScore-10) {
level = 'A';
}else if(score[i]>=maxScore-20) {
level = 'B';
}else if(score[i]>=maxScore-30){
level = 'C';
}else {
level = 'D';
}
System.out.println("第"+(i+1)+"个学生的成绩"+score[i]+",等级是"+level);
}
}
}
多维数组的使用
Java语言里提供了支持多维数组的语法。
如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格,像Excel中的表格一样。
对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。从数组底层的运行机制来看,其实没有多维数组。
二维数组[][]:数组中的数组
格式1(动态初始化):int[][] arr = new int [3][2];
定义了名称为arr的二维数组
二维数组中有3个一维数组
每一个一维数组中有2个元素
一维数组的名称分别为arr[0],arr [1],arr[2]
给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;
格式 2(动态初始化):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]; //非法
格式 3(静态初始化):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是二维数组。
Java中多维数组不必都是规则矩阵形式
| |
数组元素的默认初始化值
针对方式int[][] arr =new int [4][3];
外层元素的初始化值为:地址值
内存元素的初始化值:与一维数组初始化情况相同
针对方式int[][] arr =new int [4][];
外层元素的初始化值为:null
内存元素的初始化值:不能调用,报空指针错
int[][] arr =new int [4][3];
System.out.println(arr[0]);//[I@15db9742 地址值
System.out.println(arr[0][0]);//0
float[][] arr =new float [4][3];
System.out.println(arr[0]);// 地址值
System.out.println(arr[0][0]);//0.0
int[][] arr =new float [4][];
System.out.println(arr[0]);// null
System.out.println(arr[0][0]);//空指针异常
二维数组内存解析
int[][] arr1 = new int[4][];
arr1[1] = new int[]{1,2,3};
arr1[2] = new int[4];
arr1[2][1] = 30;
练习
1.获取arr数组中所有元素的和。
提示:使用for的嵌套循环
public class Score {
public static void main(String[] args) {
int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
int sum = 0;
for (int i =0;i<arr.length;i++) {
for (int j =0;j<arr[i].length;j++) {
sum+=arr[i][j];
}
}
System.out.println(sum);
}
}
2.声明:int[] x,y[];再给变量赋值以后,可以通过编译的是:
x[0]=y; y[0]=x; y[0][0]=x; x[0][0]=y;y[0][0]=x[0]; x=y
一维数组:int[] x或者int x[];二维数组 int[][] y,int[] y[],int y[][]
3.使用二维数组打印一个10行杨辉三角。
a[i][j] = a[i-1][j-1]+a[i-1][j]
public class Score {
public static void main(String[] args) {
//1.声明并初始化二维数组
int[][] arr = new int[10][];
//2.给数组的元素赋值
for (int i=0;i<arr.length;i++) {
arr[i] = new int[i+1];
//首末行元素赋值
arr[i][0] = arr[i][i]=1;
for (int j=1;j<arr[i].length-1;j++) {
arr[i][j] = arr[i-1][j-1]+arr[i-1][j];
}
}
for(int i=0;i<arr.length;i++) {
for(int j = 0;j<arr[i].length;j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
}
创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值。同时要求元素的值各不相同。
public class Score {
public static void main(String[] args) {
int[] arr = new int[6];
for (int i = 0;i < arr.length ;i++) {
arr[i] = (int)(Math.random()*6+1);
for (int j = 0;j < i;j++) {
if(arr[j] == arr[i]) {
i--;
break;
}
}
}
for (int value:arr) {
System.out.print(value+" ");
}
}
}
数组中涉及到的常见算法
1. 数组元素的赋值 (杨辉三角、回形数等 )
2. 求数值型数组中元素的最大值、最小值、平均数、总和等
3. 数组的复制 、反转、查找 (线性查找 、二分法查找)
4. 数组元素的排序算法
练习
1.定义一个int型的一维数组,包含10个元素, 分别赋一些随机整数, 然后求出所有元素的最大值, 最小值,和 值,平均值, 平均值, 并输出 出来 。
要求: 所有随机数都是两位。
public class Score {
public static void main(String[] args) {
int[] arr = new int[10];
int sum = 0;
int max,min;
arr[0] = (int)(Math.random()*90+10);
max = min =arr[0];
for (int i = 1; i < arr.length;i++) {
arr[i] = (int)(Math.random()*90+10);
sum+=arr[i];
if (arr[i]>max) {
max = arr[i];
}
if (arr[i]<min) {
min = arr[i];
}
}
for(int varchar:arr) {
System.out.print(varchar+" ");
}
System.out.println("sum is:"+sum);
System.out.println("min is:"+min);
System.out.println("max is:"+max);
System.out.println("avg is:"+(sum/10.0));
}
2.使用简单数组
(1) 创建一个名为ArrayTest 的类,在 main() 方法中声明 array1和array2两个变量,他们 是int[] 类型的数组。
(2) 使用大括号 {} ,把 array1初始化为 8个素数: 2,3,5,7,11,13,17,19
(3) 显示 array1的内容。
(4) 赋值array2变量等于array1,修改 array2中的偶索引元素,使其等于索引值 (如array[0]=0,array[2]=2) 。打印出 array1 。
public class Score {
public static void main(String[] args) {
int[] arr1,arr2;
arr1 = new int[] {2,3,5,7,11,13,17,19};
for (int index:arr1) {
System.out.print(index+"\t");
}
arr2 = arr1;
System.out.println();
for (int i = 0;i<arr2.length;i++) {
if (i%2==0) {
arr2[i] = i;
}
System.out.print(arr1[i]+"\t");
}
}
arr2 = arr1 //不能称作数组的复制。arr1和arr2地址值相同,都指向了堆空间的唯一的数组实体
数组的复制
arr2对arr1的复制:
int[] arr2 = new int [arr1.length];
for(i=0;i<arr1.length;i++){
arr2[i] = arr1[i]
};
数组的反转
方法一:
for(i=0;i<(arr.length)/2;i++){
int temp = arr[i];
arr[i] = arr[arr.length-i-1];
arr[arr.length-i-1] = temp;
};
方法二:
for(i=0,j=arr.length-1;i<j;i++,j--){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
};
查找
线性查找
//线性查找
public class Score {
public static void main(String[] args) {
String[] arr = new String[] {"JJ","DD","MM","BB","GG","AA"};
String dest = "B";
boolean isFlag = true;
for (int i =0;i<arr.length;i++) {
if(dest.equals(arr[i])) {
System.out.println("找到了指定的元素,位置是"+i);
isFlag = false;
break;
}
}
if(isFlag) {
System.out.println("哈啊哈没找到");
}
}
二分法查找(要查找的数组必须有序)
public class Score {
public static void main(String[] args) {
int[] arr = new int[] {-98,-45,2,23,46,98};
int dest = 9;
int head = 0;//初始索引
int end = arr.length-1;//初始的末索引
boolean isFlag = true;
while(head<=end) {
int mid = (head+end)/2;
if (dest == arr[mid]) {
System.out.println("找到,索引为"+mid);
isFlag = false;
break;
}else if(dest>arr[mid]){
head = mid+1;
}else {
end = mid -1;
}
}
if (isFlag) {
System.out.println("没找到");
}
}
}
排序算法
排序:假设含有n个记录的序列为 {R1 ,R2 ,..., Rn }, 其相应的关键字序列为 {K1 ,K2 ,..., Kn }。将这些记录重新排序为 {Ri1,Ri2,...,Rin}, 使得相应的关键字值满足条件Ki1<=Ki2<=...<=Kin,这样的一种操作称为排序。
通常来说,排序的目的是快速查找。
衡量排序算法的优劣:
1. 时间复杂度 :分析关键字的比较次数和记录的移动次数
2. 空间复杂度: 分析排序算法中需要多少辅助内存
3. 稳定性: 若两个记录A和B的关键字值相等,但排序后 A、B的先后次序保持不变,则称这种排序算法是稳定的。
排序算法分类: 内部排序 和外部排序 。
内部排序 :整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
外部排序 :参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。
可以认为外部排序由多次内部排序组成。
十大内部排序算法
关于十大排序算法的详细思想见专门开辟的章节排序算法,此处要求会写标红的排序算法,了解标黄的排序算法思想
选择排序
直接选择排序、 堆排序
交换排序
冒泡排序 、快速排序
插入排序
直接插入排序、 折半插入排序、 Shell排序
归并排序
桶式排序
基数排序
算法的五大特征
冒泡排序
基本思想 :
通过对待排序序列从前向后,依次比较相邻元素的排序码,若发生逆序则交换,使排序码较大的元素从前部向后移动。排序过程中,各元素不断接近自己的位置,如果一趟排序下来没有进行过交换,就说明有序。因此设置一个标志swap判断元素是否进行过交换,从而减少不必要的比较。
public class BubbleSort {
public static void main(String[] args) {
int[] arr = new int[] {-90,56,100};
int temp=0;
boolean swap = false;
for (int i = 0;i < arr.length-1;i++) {
for (int j = 0;j < arr.length-1-i;j++) {
if (arr[j] > arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
swap = true;
}
}
if (!swap) {
break;
}
}
}
}
快速排序
快速排序通常明显比同为 O(nlogn) 的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试中能经常看到快排的影子。可见掌握快排的重要性 。
快速排序(Quick Sort )由图灵奖获得者Tony Hoare 发明,被列为 20 世纪十大算法之一 ,是迄今为止所有内排序算法中速度最快的一种。快排时间复杂度为 O(nlog(n)) 。
排序思想:
1. 从数列中挑出一个元素,称为 "基准 "(pivot)
2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准后面(相同数可以放到任一边。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区( partition )操作。
3. 递归地( recursive)把小于基准值元素的子数列和大于基准值元素的子序列排序。
4. 递归的最底部情形,是数列大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束。因为在每次的迭代(iteration)中,它至少会把一个元素摆到最后的位置去 。
练习:49 38 65 97 76 13 27 49
public class QuickSort {
private static void swap(int[] data, int i, int j) {
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
private static void subSort(int[] data, int start, int end) {
if (start < end) {
int base = data[start];
int low = start;
int high = end + 1;
while (true) {
while (low < end && data[++low] - base <= 0)
;
while (high > start && data[--high] - base >= 0)
;
if (low < high) {
swap(data, low, high);
} else {
break;
}
}
swap(data, start, high);
subSort(data, start, high - 1);//递归调用
subSort(data, high + 1, end);
}
}
public static void quickSort(int[] data){
subSort(data,0,data.length-1);
}
public static void main(String[] args) {
int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
quickSort(data);
System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
}
}
排序算法性能对比
Arrays工具类的使用
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法 。
int[] arr1 =new int[]{1,2,3,4,};
int[] arr2 =new int[]{1,3,2,4,};
boolean isEquals = Arrays.equals(arr1,arr2) //flase
System.out.print(Arrays.toString(arr1)); //直接输出[1,2,3,4]
Arrays.fill(arr1,10) //[10,10,10,10] 将指定元素填充到数组
Arrays.sort(arr2) // [1,2,3,4] 排序