数组
数组的概念: 存储相同数据类型的一组连续的数据的容器【这个容器只在内存在有效】
数组的本质: 还是变量,只不过是一个容器变量,只不过这个变量中存储的不是基本数据类型,而是地址
注意: :凡是变量中存放的是地址,那么这个变量一定引用数据类型
如何存放一个地址到变量中呢?
int a = 10;
String s = 0x0001;
将地址赋值给一个变量必须通过 new 的方式
数组声明的格式:
数据类型[] 数组名; Java写法
int[] arr = null;
变式: 数据类型 数组名[]; C/C++ 写法
int arr[] = null;
数组的初始化【动态初始化】
数据类型[] 数组名 = new 数据类型[数组中元素的个数];
double[] scores = new double[3];
System.out.println(scores); // [D@7852e9
访问数组元素的格式:
数组名[下标/索引]
下标/索引 从0开始
数组的特点:
1.既然数组也是一个变量,那么必须先声明再赋值再使用
2.这里的数据类型既可以是八大基本数据类型,也可以是引用数据类型
3.数组名的命名规范,和变量保持一致,但是一般是复数
The local variable scores may not have been initialized
4.数组是引用数据类型,默认没有地址需要赋值为null
ArrayIndexOutOfBoundsException
异常名称: 数组索引超出边界异常
产生原因: 索引不在 [0,数组的长度-1)
解决办法: 检查索引是否在范围之内
NullPointerException
异常名称: 空指针异常
产生原因: 对象[数组 类]没有new,就访问了对象的元素、内容,没有new就没有地址,没有地址就没有指针
解决办法: 找到相对应错误行的那个引用类型,new之
数组的初始化
动态初始化: 初始化的同时不给出默认值,由系统给出默认值,默认值的规则满足堆区默认值的规则,必须指定数组的长度
数据类型[] 数组名 = new 数据类型[数组中元素的个数];
静态初始化: 初始化的同时给出元素的值,系统会根据给出元素的个数去计算数组的长度大小,不需要指定数组的长度
格式一: 数据类型[] 数组名 = {元素1, 元素2, 元素3, … 元素n };
int[] arr = { 11, 22, 33, 44, 55 };
***格式二:*** 数据类型[] 数组名 = new int[] {元素1, 元素2, 元素3, ... 元素n };
arr = new int[] { 77, 88, 99, 100, 101 };
数组的遍历: 访问数组的每一个元素
例:
功能: 遍历数组
返回值类型: void
参数列表: int[] arr
方法名: printArray
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void printArray(double[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
大家不需要自己遍历,系统JRE提供了一个工具类叫做 Arrays,这里面提供了遍历的方法
System.out.println("===================");
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(arr2));
快速初始化的三种方式:
1.通过静态初始化
int[] arr = { 11, 22, 33, 44, 55 };
2.通过键盘输入
Scanner input = new Scanner(System.in);
3.通过随机数
//书写一个方法生成任意范围的随机数
public static int getRandomNum(int start, int end) {
return (int) (Math.random() * (end - start + 1) + start);
}
}
值传递和引用传递
传递: 实参传递形参的过程
形参的类型可以是基本数据类型,也可以是引用数据类型
public class ArrayDemo05 {
public static void main(String[] args) {
int a = 10;
System.out.println("方法调用前a的值为: " + a); //值为 10
change(a);
System.out.println("方法调用后a的值为: " + a); //值为 10
}
// 类型是基本数据类型的情况
public static void change(int a) {
a += 5;
System.out.println("方法中a的值是: " + a);//值为 15
}
}
总结: 当形参是基本数据类型的时候,值传递传递的数值本身
引用传递
形参是引用数据类型的情况
引用数类型
数组
类
接口
public class ArrayDemo06 {
public static void main(String[] args) {
int[] arr = {11, 22, 33};
System.out.println("方法调用前数组中的元素是: " + Arrays.toString(arr));
change(arr);
System.out.println("方法调用前数组中的元素是: " + Arrays.toString(arr));
}
public static void change(int[] arr) {
arr[1] = 666;
System.out.println("方法调用中数组中的元素是: " + Arrays.toString(arr));
}
}
总结:
当形参是基本数据类型的时候,传递的是数值本身
当形参是引用数据类型的时候,传递的是地址
当存在多个引用指向同一个堆区的空间的时候,有任何一个引用修改了堆区的内容,都会影响到所有的引用
基本查找
功能: 查找某个数在数组中的索引
返回值类型: int
参数列表: int[] arr, int num
方法名: baiscSearch 【基本查找】
public static int basicSearch(int[] arr, int num) {
int index = -1;
for (int i = 0; i < arr.length; i++) {
if (num == arr[i]) {
index = i;
break;
}
}
return index;
}
}
冒泡排序法: 相邻两个元素进行比较,如果左边的数大于后面的数,就交换两个数的位置,一趟比较结束后,最大值就出现在了最后面。
特点:
1.相邻两个元素进行比较,大者冒泡
2.一共比较 arr.length - 1 趟
3.每一趟比较的次数比上一趟少一次
分析代码部分:
* 第一趟排序:
* arr[0] 和 arr[1] 比较
* arr[1] 和 arr[2] 比较
* arr[2] 和 arr[3] 比较
* arr[3] 和 arr[4] 比较
*
* 一共比较arr.length - 1次
*/
/*for (int i = 0; i < arr.length - 1 - 0; i++) {
if (arr[i] > arr[i+1]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第一趟排序后: " + Arrays.toString(arr));
* 第二趟排序:
* arr[0] 和 arr[1] 比较
* arr[1] 和 arr[2] 比较
* arr[2] 和 arr[3] 比较
*
* 一共比较arr.length - 1 - 1次
for (int i = 0; i < arr.length - 1 - 1; i++) {
if (arr[i] > arr[i+1]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第二趟排序后: " + Arrays.toString(arr));
* 第三趟排序:
* arr[0] 和 arr[1] 比较
* arr[1] 和 arr[2] 比较
*
* 一共比较arr.length - 1 - 2次
for (int i = 0; i < arr.length - 1 - 2; i++) {
if (arr[i] > arr[i+1]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第三趟排序后: " + Arrays.toString(arr));
* 第四趟排序:
* arr[0] 和 arr[1] 比较
* arr[1] 和 arr[2] 比较
*
* 一共比较arr.length - 1 - 3次
for (int i = 0; i < arr.length - 1 - 3; i++) {
if (arr[i] > arr[i+1]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println("第四趟排序后: " + Arrays.toString(arr));*/
总结规律后代码部分:
public class BubbleSortDemo {
public static void main(String[] args) {
int[] arr = {24, 69, 80, 55, 13};
System.out.println("排序前: " + Arrays.toString(arr));
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]) {
int temp = 0;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println("冒泡排序后: " + Arrays.toString(arr));
}
}
插入排序:
思路
1.从第一个元素开始,该元素可以认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后向前扫描
3.如果该元素(已排序)大于新元素,将该元素移到下一位置
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置后
6.重复步骤2~5
分析代码部分:
/*
* 第一趟排序
* arr[1] 和 arr[0] 进行比较
* 比较一次
*/
/*int i = 1;
for (int j = 0; j < 1; j++) {
if (arr[i] < arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第一趟排序后: " + Arrays.toString(arr));
第二趟排序
* arr[2] 和 arr[0] 进行比较
* arr[2] 和 arr[1] 进行比较
* 比较2次
*
i = 2;
for (int j = 0; j < 2; j++) {
if (arr[i] < arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第二趟排序后: " + Arrays.toString(arr));
第三趟排序
* arr[3] 和 arr[0] 进行比较
* arr[3] 和 arr[1] 进行比较
* arr[3] 和 arr[2] 进行比较
* 比较3次
*
i = 3;
for (int j = 0; j < 3; j++) {
if (arr[i] < arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第三趟排序后: " + Arrays.toString(arr));
第四趟排序
* arr[4] 和 arr[0] 进行比较
* arr[4] 和 arr[1] 进行比较
* arr[4] 和 arr[2] 进行比较
* arr[4] 和 arr[3] 进行比较
* 比较4次
i = 4;
for (int j = 0; j < 4; j++) {
if (arr[i] < arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第四趟排序后: " + Arrays.toString(arr));*/
总结规律后代码部分:
public class InsertSortDemo {
public static void main(String[] args) {
int[] arr = {24, 69, 80, 55, 13};
System.out.println("排序前: " + Arrays.toString(arr));
for (int i = 1; i < arr.length ; i++) {
for (int j = 0; j < i; j++) {
if (arr[i] < arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println("插入排序后: " + Arrays.toString(arr));
}
}
选择排序:
***选择排序思想:*** 从最左边开始,依次和后面每一个元素比较,
如果后面元素比第一个小,就交换位置,第一趟排序之后,最小数出现在了前面。
特点:
1.左边的值依次和后面每一个元素比较
2.一共比较了arr.length - 1 趟
3.每一趟比上一趟少比较1次
分析代码部分:
* 第一趟排序
* arr[0] 和 arr[1]
* arr[0] 和 arr[2]
* arr[0] 和 arr[3]
* arr[0] 和 arr[4]
*
* 一共比较了arr.length - 1次
/*int i = 0;
for (int j = i+1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第一趟排序后: " + Arrays.toString(arr));
* 第二趟排序
* arr[1] 和 arr[2]
* arr[1] 和 arr[3]
* arr[1] 和 arr[4]
i = 1;
for (int j = i+1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第二趟排序后: " + Arrays.toString(arr));
* 第三趟排序
* arr[2] 和 arr[3]
* arr[2] 和 arr[4]
i = 2;
for (int j = i+1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第三趟排序后: " + Arrays.toString(arr));
* 第四趟排序
* arr[3] 和 arr[4]
i = 3;
for (int j = i+1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.println("第四趟排序后: " + Arrays.toString(arr));
总结规律后代码部分:
public class SelectSortDemo {
public static void main(String[] args) {
int[] arr = {44, 89, 100, 77, 33};
System.out.println("排序前: " + Arrays.toString(arr));
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i+1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println("选择排序后: " + Arrays.toString(arr));
}
}
快速排序法:
Arrays.sort(arr); ---> Arrays方法
二分法查找/折半查找:
只针对排序好的元素再来进行二分。
/*
* 功能: 二分查找
* 返回值类型: int
* 参数列表: int[] arr, int num
* 方法名: binarySearch
*/
public static int binarySearch(int[] arr, int num) {
// 1.定义最小索引和最大索引
int min = 0;
int max = arr.length - 1;
// 2.计算中间索引
int mid = (min + max) / 2;
// 3.拿中间索引所对应的数值和需要查找的数 num 进行比较
while (arr[mid] != num) {
// 大了,左边找
if (arr[mid] > num) {
max = mid - 1;
// 小了,右边找
} else if (arr[mid] < num) {
min = mid + 1;
}
if (min > max) {
return -1;
}
// 重新计算中间索引
mid = (min + max) / 2;
}
return mid;
}
}
二维数组:
概要:二维数组其实是一位数组的嵌套(每一行看做一个内层的一维数组)
二维数组内存结构:
[外链图片转存失败(img-m8E81XIU-1568552958129)(E:\JavaEE\javaSE\day05\01_课件资料\img\Snipaste_2019-09-14_16-16-49.png)]
两种初始化形式
格式1: 动态初始化
数据类型 数组名 [ ][ ] = new 数据类型[m][n]
数据类型 [ ][ ] 数组名 = new 数据类型[m][n]
数据类型 [ ] 数组名 [ ] = new 数据类型[m][n]
举例:int [ ][ ] arr=new int [5][3]; 也可以理解为“5行3例”
格式2: 静态初始化
数据类型 [ ][ ] 数组名 = {{元素1,元素2…},{元素1,元素2…},{元素1,元素2…}…};
举例:int [ ][ ] arr={{22,15,32,20,18},{12,21,25,19,33},{14,58,34,24,66},};
静态初始化可用于不规则二维数组的初始化
public static void main(String[]args){
int [][] arr=new int[][]{{4,5,6,8},{2,3},{1,6,9}};
System.out.println(arr.length);//输出行数
System.out.println(arr[0].length);//输出列数
}
输出结果:
[外链图片转存失败(img-nbHfADOC-1568552958143)(E:\JavaEE\javaSE\day05\01_课件资料\img\Snipaste_2019-09-14_16-16-26.png)]
例:
实现一个M*N的二维数组的转置并输出:
public static void main(String[]args){
int [][] arr=new int[][]{{4,5,6},{2,3,9}};
int [][]arrtrans=new int[arr[0].length][arr.length];
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[0].length;j++){
arrtrans[j][i]=arr[i][j];
}
}
for(int i=0;i<arrtrans.length;i++){
for(int j=0;j<arrtrans[0].length;j++){
System.out.print(arrtrans[i][j]);
}
System.out.println();
}
}