一、 数组的初始化以及内存分布图
1.数组的定义:
固定大小存储统一数据类型元素数据的容器
2.特点:
(1)大小是固定的
(2)对于同一个数组而言,元素数据类型是一样的
(3)对于不同的数组,他们的元素数据类型可以是不一样的
(4)数组既可以存储基本数据类型,也可以存储引用数据类型
3.数组的定义格式:
第一种: 数据类型 [] 数组名;
第二种: 数据类型 数组名 [];
注意:
数组只是定义,就相当于定义了一个没有值的变量,无法直接使用。 给值的过程实际上就是初始化值的过程。
4.数组的初始化
java中数组的初始化有两种初始化方式:
1、动态初始化:我们指定数组的大小,初始化值由系统决定
byte,short,int,long类型的数组初始化默认值为0;
float,double类型的数组的初始化默认值为0.0;
布尔类型的数组的初始化默认值为false;
char类型的数组的初始化默认值为’\u0000’;
引用类型的数组的初始化默认值为null;
2、静态初始化:在创建数组的时候,我们将元素一并赋值上去,由系统来判断数组的大小
4.1动态初始化:
语句定义格式: 数据类型[] 数组名 = new 数据类型[元素个数];
举例:int[] arr = new int[3];
其中 []: 表示这是一个一维数组
new:表示在堆内存中开辟空间
4.2静态初始化
语句定义格式: 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,...};
简化写法: 数据类型[] 数据名 = {元素1,元素2,元素3,...};
举例:创建一个存储了11,22,33,44,55这些元素的一维数组
int[] arr = new int[]{11,22,33,44,55};
简化写法: int[] arr = {11,22,33,44,55};
5.数组的索引操作
1.利用索引得到数组中存储的元素
2.索引操作时的常见问题:
3.演示:
int [] arr1={11,22,33,44,55};
int [] arr2=null;
System.out.println(arr1[0]);
System.out.println(arr1[4]);
System.out.println(arr1.length); //获取数组的长度
System.out.println(arr1[5]); //数组索引越界
System.out.println(arr2[0]); //空指针异常
6. Java中的内存分配
内存图解:
图解1: 静态初始化
图解2: 定义两个数组,先定义一个数组,赋值,输出。然后定义第二个数组的时候把第一个数组的地址赋值给第二个数组。然后给第二个数组赋值,再次输出两个数组的名及元素。
图解3:方法传参的问题
总结:
(1)方法传参时,当基本数据类型作为方法的参数传递时候,外部的变量值不会受到影响
当引用数据类型作为方法的参数传递的时候,堆内存中的数据值会受到影响
(2)==比较:
1、如果比较的是基本数据类型,比较的是数值
2、如果比较的是引用数据类型,比较的是地址值
7.练习
(1)数组遍历(依次输出数组中的每一个元素),并以数组的形式打印在控制台
int [] arr1 = {11,22,33,44,55,66,77,888,999,189};
for (int i = 0; i < arr1.length; i++) {
if(i==0){
System.out.print("["+arr1[i]);
} else if (i==arr1.length-1) {
System.out.print(","+arr1[i]+"]");
}else{
System.out.print(","+arr1[i]);
}
}
结果: [11,22,33,44,55,66,77,888,999,189]
(2)获取数组中的最大值最小值
int[] arr = {11, 23, 31, 4, 12, 41, 11, 31, 4, 12, 41, 11};
//1、默认第一个元素为最大值和最小值
int maxNumber = arr[0];
int minNumber = arr[0];
//2、从第二个元素开始依次遍历,与最大值和最小值进行比较
for (int i = 1; i < arr.length; i++) {
if (arr[i] > maxNumber) {
maxNumber = arr[i];
}
if (arr[i] < minNumber) {
minNumber = arr[i];
}
}
System.out.println("最大值为:" + maxNumber);
System.out.println("最小值为:" + minNumber);
结果: 最大值为:41
最小值为:4
(3)数组元素查找(查找指定元素第一次在数组中出现的索引)
Scanner sc = new Scanner(System.in);
System.out.print("请输入一个元素:");
int numnber = sc.nextInt();
int[] arr1 = {11, 22, 33, 44, 55, 66, 77, 888, 999, 11, 189, 999};
boolean flag = true; // 定义标志位
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] == numnber) {
System.out.println("该元素的索引为"+i);
flag = false;
break;
}
}
if (flag) {
System.out.println("没有该元素!!");
}
结果:请输入一个元素:33
该元素的索引为2
注意:
如果数组是String类型,要想比较内容值的话,String类中有一个方法equals方法。
使用方式:确定值的字符串.equals(被比较的字符串);
举例:比较字符串"java"与变量s1的值是否相等:
方式1:s1.equals("java") 不推荐 当s1为空的时候,会发生空指针异常
方式2:"java".equals(s1) 推荐 永远不会发生空指针异常
(4)综合题:
某个公司采用公用电话传递数据信息,数据是小于8位的整数,为了确保安全, 在传递过程中需要加密,加密规则如下: 首先将数据倒序,然后将每位数字都加上5,再用和除以10的余数代替该数字, 最后将第一位和最后一位数字交换。 请任意给定一个小于8位的整数, 然后,把加密后的结果在控制台打印出来。
int[] arr = {3, 4, 1, 2, 5, 2, 1, 2};
System.out.println("逆序前:");
printArray(arr);
//1、
int[] arr2 = niXu(arr);
// System.out.println("逆序后:");
// printArray(arr2);
//2、
for (int i = 0; i < arr2.length; i++) {
//每位数字都加上5,用和除以10的余数
arr2[i] = (arr2[i] + 5) % 10;
}
//3、
//最后将第一位和最后一位数字交换
int tmp = arr2[0];
arr2[0] = arr2[arr2.length - 1];
arr2[arr2.length - 1] = tmp;
System.out.println("加密后:");
printArray(arr2);
}
public static int[] niXu(int[] arr) {
for (int start = 0, end = arr.length - 1; start < end; start++, end--) {
int tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
}
return arr;
}
public static void printArray(int[] arr) {
for (int index = 0; index < arr.length; index++) {
if (index == 0) {
System.out.print("[" + arr[index] + ",");
} else if (index == arr.length - 1) {
System.out.println(arr[index] + "]");
} else {
System.out.print(arr[index] + ",");
}
}
}
本题中逆序的思想是利用两个指针变量start,end不断向中间靠拢,不断交换两边的值,直到start大于等于end时,循环停止,此时两边的数据已全部交换完成,则逆序完成。
二.二维数组
1.二维数组:元素为一维数组的数组
2.如何定义一个二维数组:
数据类型[][] 数组名; (规范写法)
数据类型[] 数组名[];
数据类型 数组名[][];
数据类型 [] [] 数组名;
数据类型 [] 数组名 [];
3.如何创建一个二维数组:
3.1语句定义格式1:
数据类型[][] 变量名 = new 数据类型[m][n];
m:表示有多少个一维数组 n:表示每个一维数组的元素个数
举例:int[][] arr = new int[3][3] 表示二维数组中有三个一维数组的元素,每个一维数组的长度为3,元素的数据类型为int
演示:
int[][] arr = new int[3][3];
System.out.println(arr); //二维数组的地址值
System.out.println(arr[0]); // 第一个一维数组元素的地址值
System.out.println(arr[1]); // 第二个一维数组元素的地址值
System.out.println(arr[2]); // 第三个一维数组元素的地址值
//获取第一个一维数组中的第二个元素值
System.out.println(arr[0][1]); //int类型默认值为0
3.2语句定义格式2:
数据类型[][] 变量名 = new 数据类型[m][];
演示:
int[][] arr = new int[3][];
System.out.println(arr[0]); //null
int [] arr1={1,2,3};
int [] arr2={4,5,6};
int [] arr3={7,8,9};
arr[0]=arr1;
arr[1]=arr2;
arr[2]=arr3;
//利用索引获取元素5
System.out.println(arr[1][1]);
3.2语句定义格式3:
数据类型[][] 变量名 = new 数据类型[][]{{元素…},{元素…},{元素…}};
简化写法: 数据类型[][] 变量名 = {{元素…},{元素…},{元素…}};
演示:
// int[][] arr = new int[][]{{11, 22, 33}, {1, 2, 3}, {100, 200, 300, 400}};
int[][] arr = {{11, 22, 33}, {1, 2, 3}, {100, 200, 300, 400}};
System.out.println(arr[2][1]); //200
// int[][] arr;
// arr = new int[][]{{11, 22, 33}, {1, 2, 3}, {100, 200, 300, 400}};
4.二维数组的遍历:
要求:以一维数组的形式打印在控制台
int[][] arr = {{11, 21, 31, 41}, {15, 16,17, 18}, {19, 17, 91, 12}};
for (int i = 0; i < arr.length; i++) { //遍历二维数组得到一维数组
for (int j = 0; j < arr[i].length; j++) { //遍历一维数组得到元素的值
if(j==0){
System.out.print("["+arr[i][j]+",");
} else if (j == arr[i].length - 1) {
System.out.print(arr[i][j]+"]");
}else {
System.out.print(arr[i][j]+",");
}
}
System.out.println();
}
三.数组排序和二分查找
1.冒泡排序:
原理:冒泡排序就是从序列中的第一个元素开始,依次对相邻的两个元素进行比较,如果前一个元素大于后一个元素则交换它们的位置。如果前一个元素小于或等于后一个元素,则不交换它们;这一比较和交换的操作一直持续到最后一个还未排好序的元素为止。
图文演示:
代码演示:
int [] arr = {34,23,43,22,22,321,74,224,64,28,54,65};
for (int i = 1; i < arr.length; i++) { //控制比较的轮次
int j = 0;
for (; j < arr.length-i; j++) { //控制每轮元素之间比较的次数
if(arr[j]>arr[j+1]){
int bigNumber=arr[j];
arr[j]=arr[j+1];
arr[j+1]=bigNumber;
}
}
}
printArray(arr);
}
public static void printArray(int[] arr) {
for (int index = 0; index < arr.length; index++) {
if (index == 0) {
System.out.print("[" + arr[index] + ",");
} else if (index == arr.length - 1) {
System.out.println(arr[index] + "]");
} else {
System.out.print(arr[index] + ",");
}
}
}
结果:[22,22,23,28,34,43,54,64,65,74,224,321]
2.反转排序
即逆序,在上文中数组初始化练习中的综合题中提到,在此不在赘述
3.选择排序
算法原理:每次从待排序的数据元素选出最小(最大)的一个元素,顺序的放在一已排好序的数列的最后,直到全部待排序的数据元素排完;(可以参考上述冒泡图来理解)
代码演示:
int[] arr = {33, 22, 44, 11, 55,324,344,54,67,88,565,23,1};
for (int i = 1; i < arr.length; i++) { //控制比较的轮次
int maxFlag = 0;
for (int j = 1; j < arr.length - i + 1; j++,maxFlag++) { //控制每轮比较的次数
if (arr[j] > arr[maxFlag]) {
int tmp =arr[j];
arr[j]=arr[maxFlag];
arr[maxFlag]=tmp;
}
}
}
MaoPaoDemo.printArray(arr);
结果:[565,344,324,88,67,55,54,44,33,23,22,11,1]
3.二分查找
二分法查找(折半查找)操作:使用二分法查找有序数组中元素。找到返回索引,不存在输出-1。 ----------------------------------------- 分析:二分法查找的前提是数组有序。!!!!!!! ----------------------------------------- 假如有一组数为3,12,24,36,55,68,75,88要查给定的值24.可设三个变量 front,mid,end分别指向数据的上界,中间和下界,mid=(front+end)/2. 1)开始令front=0(指向3),end=7(指向88),则mid=3(指向36)。因为mid>x, 故应在前半段中查找。 2)令新的end=mid-1=2,而front=0不变,则新的mid=1。此时x>mid,故确定应在后半段中查找。 3)令新的front=mid+1=2,而end=2不变,则新mid=2,此时a[mid]=x,查找成功。 4)如要查找的数不是数列中的数,例如x=25,当第三次判断时,x>a[mid],按以上规律,令front=mid+1,即front=3,出现front>end的情况,表示查找不成功。
代码演示:
int[] arr = {3, 12, 24, 36, 55, 68, 75, 88};
int number = 18;
int front = 0;
int end = arr.length - 1;
int mid = (front + end) / 2;
boolean flag = true;
while (front <= end) {
if (number > arr[mid]) {
front = mid + 1;
} else if (number < arr[mid]) {
end = mid - 1;
} else {
System.out.println("找到该元素,索引为:" + mid);
flag = false;
break;
}
//重新算中间位置
mid = (front + end) / 2;
}
if (flag) {
System.out.println("没有该元素!");
}