一、数组
数组(array)是多个相同数据类型按照一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理
数组的相关概念:
- 数组名
- 元素
- 角标(下标、索引):数组的索引从0开始,到数组长度-1结束
- 长度
数组的特点:
- 数据是有序排列的
- 数组是引用类型变量。数组的元素可以是基本数据类型,也可以是引用数据类型
- 数据对象会在内存开辟一块连续的空间
- 数组的长度一旦确定,不能更改
数组的分类:
- 按照维数:一维数组、二维数组……
- 按照数组元素类型:基本数据类型元素的数组、引用数据类型元素的数组
一维数组的使用:
- 一维数组的声明和初始化
-
int[] ids; // 声明 ids = new int[]{1001, 1002, 1003, 1004}; // 静态初始化:数组的初始化和数组元素的赋值同时进行 String[] names = new String[5]; //动态初始化:数组的初始化和数组元素的赋值分开进行
-
- 如何调用数组指定位置的元素
-
names[0] = "小陈"; names[1] = "小吴"; names[2] = "小李"; names[3] = "老邓"; names[4] = "小王"; // names[5] = "小邓"; // 报错,java.lang.ArrayIndexOutOfBoundsException
-
- 如何获取数组的长度
-
System.out.println(names.length); // 5
-
- 如何遍历数组
-
for (int i=0;i<names.length;i++){ System.out.println(names[i]); }
-
- 数组元素的默认初始化值
- 数组元素是整形:0
- 数组元素是浮点型:0.0
- 数组元素是char型:0或'\u0000',而非'0'
- 数组元素是布尔值:false
- 数组元素是引用数据类型:null
-
String[] arr = new String[4]; for (int i=0;i<arr.length;i++){ System.out.print(arr[i] + "\t"); } // null null null null
- 数组的内存解析
- 简化版内存结构
-
例题:UN公社单间短期出租4个月,1550元/月(水电煤公摊,网费35元/月),空调、卫生间、厨房齐全。屋内均是IT行业人员,喜欢安静。所以要求来租者最好是同行或者刚毕业的年轻人,爱干净。安静,联系方式:
public class TestDemo {
public static void main(String[] args) {
int[] arr = new int[]{8, 2, 1, 0, 3};
int[] index = new int[]{2, 0, 3, 2, 4, 0, 1, 3, 2, 3, 3};
String tel = "";
for (int i = 0; i < index.length; i++) {
tel += arr[index[i]];
}
System.out.println("联系方式:" + tel);
}
}
二维数组的使用
对于二维数组的理解,我们可以看成是以为数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,没有多维数组
- 二维数组的声明和初始化
-
public class TestDemo { public static void main(String[] args) { int[][] ids; // 声明 ids = new int[][]{{1,2,3},{4,5},{6,7,8,9}}; // 静态初始化:数组的初始化和数组元素的赋值同时进行 int[][] ids2= {{1,2,3},{4,5},{6,7,8,9}}; //类型推断,也是正确写法 String[][] names = new String[3][2]; //动态初始化1:数组的初始化和数组元素的赋值分开进行 String[][] names2 = new String[3][]; //动态初始化2:数组的初始化和数组元素的赋值分开进行 String[] names3[] = new String[3][]; //也是正确写法 } }
-
- 如何调用数组指定位置的元素
-
System.out.println(ids[0][1]); //2 System.out.println(names[1][1]); //null System.out.println(names2[1]); //null names2[1] = new String[4]; System.out.println(names2[1][1]); //null
-
- 如何获取数组的长度
-
System.out.println(names.length); //3 System.out.println(ids[2].length); //4
-
- 如何遍历数组
-
for(int i=0;i<ids.length;i++){ for(int j=0;j<ids[i].length;j++){ System.out.print(ids[i][j]+"\t"); } System.out.println(); } // 1 2 3 // 4 5 // 6 7 8 9
-
- 数组元素的默认初始化值
- 针对初始化方式一:比如:int[][] arr = new int[4][3];
- 外层元素的初始化值为:地址值
- 内层元素的初始化值为:与一位数组初始化值情况相同
- 针对初始化方式二:比如:int[][] arr = new int[4][];
- 外层元素的初始化值为:null
- 内层元素的初始化值为:不能调用,报空指针错误
- 数组的内存解析
-
例题:
1、打印杨辉三角
public class TestDemo {
public static void main(String[] args) {
// 杨辉三角
int[][] yangHui= new int[10][];
for(int i=0;i<yangHui.length;i++){
yangHui[i]=new int[i+1];
yangHui[i][0] = yangHui[i][i] = 1; // 首尾赋值为1
// 给中间位置赋值
for(int j=1;j<yangHui[i].length-1;j++){
yangHui[i][j]=yangHui[i-1][j-1]+yangHui[i-1][j];
}
}
// 遍历数组
for(int i=0;i<yangHui.length;i++){
for (int j=0;j<yangHui[i].length;j++){
System.out.print(yangHui[i][j]+"\t");
}
System.out.println();
}
}
}
2、创建一个长度为6的int型数组,要求取值为1-30,同时元素值各不相同
public class TestDemo {
public static void main(String[] args) {
// 创建一个长度为6的int型数组,要求取值为1-30,同时元素值各不相同
int[] arr = new int[6];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 30 + 1);
for (int j = 0; j < i; j++) {
if (arr[i] == arr[j]) {
i--;
break;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
3、求数组中元素的最大值、最小值、平均数、总和
定义一个int型的一维数组,包含10个元素,分别赋一些随机数,然后求出所有元素的最大值、最小值、和值、平均数,并输出
要求:所有随机数都是两位数
public class TestDemo {
public static void main(String[] args) {
//定义一个int型的一维数组,包含10个元素,分别赋一些随机数,然后求出所有元素的最大值、最小值、和值、平均数,并输出
//要求:所有随机数都是两位数[10,99]
int[] arr = new int[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 88 + 10); //公式:[a,b]:(int) (Math.random() * (b-a+1) + a)
System.out.print(arr[i] + "\t");
}
System.out.println();
// 最大值
int maxValue = arr[0];
for (int i = 1; i < arr.length; i++) {
if (maxValue < arr[i]) {
maxValue = arr[i];
}
}
System.out.println("最大值:" + maxValue);
// 最小值
int minValue = arr[0];
for (int i = 1; i < arr.length; i++) {
if (minValue > arr[i]) {
minValue = arr[i];
}
}
System.out.println("最小值:" + minValue);
// 和值
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println("总和值:" + sum);
// 平均值
double avg = sum / arr.length;
System.out.println("平均值:" + avg);
}
}
4、数组的引用
public class TestDemo {
public static void main(String[] args) {
int[] arry1,arry2;
arry1=new int[]{8,9,65,32,56,23,7,5,43};
arry2=arry1; // arry2引用指向arry1,注意此时arry1与arry2是同一个数组,不是复制
// 此时修改arry1的值后,arry2的值会随之修改
for(int i=0;i<arry1.length;i++){
if(i%2==0){
arry1[i] = i;
}
}
for(int i=0;i<arry2.length;i++){
System.out.print(arry2[i]+"\t"); // 0 9 2 32 4 23 6 5 8
}
}
}
5、数组的复制
public class TestDemo {
public static void main(String[] args) {
int[] arry1,arry2;
arry1=new int[]{8,9,65,32,56,23,7,5,43};
arry2=new int[9];
// 复制数组arry1
for(int i=0;i<arry1.length;i++){
arry2[i]=arry1[i];
}
for(int i=0;i<arry1.length;i++){
if(i%2==0){
arry1[i] = i; //此时修改arry1后,arry2的值不变
}
}
for(int i=0;i<arry2.length;i++){
System.out.print(arry2[i]+"\t"); // 8 9 65 32 56 23 7 5 43
}
}
}
6、数组的反转
public class TestDemo {
public static void main(String[] args) {
int[] arry = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
// 数组的反转
// 方法一
// for (int i = 0; i < arry.length / 2; i++) {
// int temp = arry[i];
// arry[i] = arry[arry.length - i - 1];
// arry[arry.length - i - 1] = temp;
// }
// 方法二
for (int i = 0, j = arry.length - 1; i < j; i++, j--) {
int temp = arry[i];
arry[i] = arry[j];
arry[j] = temp;
}
for (int i = 0; i < arry.length; i++) {
System.out.print(arry[i] + "\t"); // 9 8 7 6 5 4 3 2 1
}
}
}
7、数组的线性查找
public class TestDemo {
public static void main(String[] args) {
String[] arry = new String[]{"aa", "bb", "cc", "dd", "ee", "ff", "gg"};
// 数组的查找
//线性查找(地毯式搜索)
String dest = "gg";
boolean isFlag = true;
for (int i = 0; i < arry.length; i++) {
if (dest.equals(arry[i])) {
System.out.println("找到了指定元素的位置:" + i);
isFlag = false;
break;
}
}
if (isFlag) {
System.out.print("很遗憾,没有找到你要找的元素呢");
}
}
}
8、数组的二分查找
public class TestDemo {
public static void main(String[] args) {
int[] arry = new int[]{-55, -23, -5, 3, 9, 13, 35, 46, 56, 67};
//二分法查找
//前提:查找的数组必须有序
int dest = 56; // 要查找的元素
int head = 0;//初始起始索引
int end = arry.length - 1;//初始的末尾索引
boolean isFlag = true;
while (head <= end) {
int middle = (head + end) / 2; //中间值
if (dest == arry[middle]) {
System.out.println("找到了你要查找的元素,位置为:" + middle);
isFlag = false;
break;
} else if (dest < arry[middle]) {
end = middle - 1;
} else if (dest > arry[middle]) {
head = middle + 1;
}
}
if (isFlag) {
System.out.print("很遗憾,没有找到你要找的元素呢");
}
}
}
数组排序
- 选择排序
- 直接选择排序
- 堆排序
- 交换排序
- 冒泡排序
- 快速排序
- 插入排序
- 直接插入排序
- 折半插入排序
- Shell排序
- 归并排序
- 桶式排序
- 基数排序
冒泡排序举例
public class TestDemo {
public static void main(String[] args) {
int[] arr = new int[]{-55, -23, -5, 3, 9, 13, 35, 46, 56, 67};
// 冒泡排序
int temp;
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;
}
}
}
//遍历排序后的数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
快速排序
原理:
demo:
举例:
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));
}
}
排序算法性能对比