第81节:Java中的数组
第81节:java中的数组
本节介绍数组的基本概念,数据就是一种数据结构,可以用来存储多个数据,每个数组中可以存放相同类型的数据。比如,在学校,我们是一个班,这里的班级中每个同学都是这个班级数组中的元素,都是同样的类型为学生,对应的学号就是我们的索引,但是在现实中的学号一般都是从1开始的,而在java中的数组索引是从0开始的。
定义一个数组为方括([]),通过数组元素的索引(或下标,角标)来访问数组中的元素,同时可以为数组赋值和取出数组的元素值。
问: 在java中为什么要有数组呢?
答: 数组就是一个容器,是用来存储同种数据类型的多个值。
数组的概念
同一种类型的数据的集合,用来装数据的,数组就是一个容器。在java中数组的好处就是可以用数组中的元素从0开始编号,可以利用下标(索引),对齐进行操作,即方便又快捷。
在java中的数组是用存储同种数组的元素,其指的是数据类型要相同,在数组中存放的数据类型是唯一的,只能存储一种数据类型,不能存储多种数据类型。数组可以存储基本数据类型,也可以存储引用数据类型。
数组的定义格式:
一般数组的定义为:
int[] array; 或 int array[];
这两种定义的语法通常都可以用,但是建议是使用 int[] array 这种语法,因为大多数程序员常用,这种语法定义更具有可读性。
格式1:
数据类型[] 数组名 = new 数组类型[元素个数或者数组的长度];
例如:
int[] arr = new int[5];
格式2:
元素类型[] 数组名 = new 元素类型[]{元素1,元素2,。。。};
例如:
int[] arr = new int[]{1,2,3,4}; int[] arr = {2,3,4,5};
数组的定义方式:
数组的表示:[],通过关键字new来创建数组
一个数组一旦初始化建立,那么数组就会在内存中有一块空间被固定下来,那么这块空间就是这个数组的,不可变,即数组的长度将不可改变。就算把这个数组中的数组清空,在内存中还是这块空间被保存下来。比如,一家酒店我们把它定义一个数组,那么每个房间就是这家就是的长度,这家酒店我们就把它当做是我们在内存中开辟的一块固定下来的空间,每个房间中入住的人就是这块空间,也就是数组的元素,房间号码我们可以当做的数组的索引,通过房间号找到相应的入住者。当这家酒店中的每个元素即是客人都走时,这家酒店中的房间依然保留着,依然还是酒店,所以依然还是数组了。数组中的长度即酒店中的房间还是这个数量(长度)。
数组代码示例:
package com。dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 数据类型[] 数组名=new 数据类型[数组的长度]; int[] arr = new int[5]; /* * int: 代表数据类型 * []: 代表数组 * arr: 合法的标识符 * * new: 创建新的实体或对象 * int: 数据类型 * []: 代表的数组 * 5: 代表数组的长度 */ } }
数组的索引
例如:
int[] arr = new int[3];
数组可以存储多个数据,并且会对数组进行编号,从0开始操作元素,可以通过编号(索引,角标,下标)找到该元素。代码中会在内存空间中开辟3个空间,如三个房子编号,从0开始,第二个房子为1,第三个房子为2。这只是一种比如,我们把它看作三个空间,对应的三个地址编号而已,通过地址是不是就可以找到房子了呢!
数组也是一种数据类型,为引用类型,如int为一种基本数据类型,那么int[]这是一种属于int数组的一种引用类型,所以int[]是一种数据类型,创建int[]类型的对象为创建数组。
什么是数组的初始化?
就是为数组开辟连续的内存空间,并为每个数据元素赋予值。
只要数组进行分配,就具有初始化值,数组变量一旦在内存空间分配了区域,就会在每个空间里存储数组的初始化值,就算内存空间为空,也会有一个初始化的值为null,这里的值会根据变量类型来给定初始化值,初始化值可以有系统进行自动分配,如果我们不给定值的话,另一种就是由我们程序员给定初始化值。
如何对数组进行初始化?
动态初始化就是程序员指定数组的长度,有系统进行数组元素的分配初始值。
例如: int[] arr = new int[5];
格式如下:
arrayname = new type[length];
使用动态初始化过程如下:
int[] array = new int[5];
静态初始化就是程序员给定初始化值,然后由系统进行决定长度。
静态初始化的语法格式:
array = new type[]{元素1,元素2,元素3,。。。};
定义一个int数组类型的变量:
int[] intarray;
静态初始化,给定数组元素的初始化值,不给定数组长度,由系统决定数组长度:
intarray = new int[]{2,3,4,5,6}; 或 intarray = {2,3,4,5,6};
在程序员的通常写法中,数组的定义和数组进行初始化都是同时完成如:
int[] a = {1,2,3,4};
代码案例:
package com。dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 数据类型[] 数组名 = new 数据类型[数组长度]; int[] arr = new int[5]; // 动态初始化,在内存中开辟连续的5块空间 system。out。println(arr[0]); // 系统会给出默认的初始化值 // 整数类型都为0 arr[0] = 12; system。out。println(arr[0]); } }
结果:
结果在内存中开辟连续的5块空间,在内存中进行存储,这5块空间有自己的地址,用于方便去找到,可以通过地址先找到该数组,如找一栋楼,需要地址,然后找数组中的元素,如每个房间,通过编号找到每个元素。
案例:
system。out。println(arr);// 打印结果 [i@7852e922// 16进制的表现形式// [ 代表数组// i 代表是int类型// @ 固定的// 7852e922 代表16进制的地址值
在java中运行程序会进行划分空间进行运行程序:五块内存空间
1.栈:用来存储局部变量的
2.堆:存储new出来的数组或对象
3.方法区:面向对象
4.本地方法区:和系统相关
5.寄存器:供给cpu使用(不需要了解)
局部变量是定义在方法声明上或方法中的变量,在栈内存中,存储的都是局部变量,只要在方法中定义的变量都是局部变量,一旦变量的生命周期结束该变量就会被释放,用完就会被删掉了。
堆内存,存储的都是实体,就是对象,凡是用new 创建的都是在堆里面。
new,一个new指在内存中进行开辟空间,在堆内存中每个实体都是一个首地址值,堆内存的变量都是有默认的初始化值的,不同类型都不一样,当实体不在使用时,堆中的变量不会马上删除,会由java系统中的垃圾回收机制进行回收(java中有个垃圾回收机制,自动回收垃圾)
数组地址,例如:0x0011,可以通过索引找到每个值,系统会给初始化值。
整数类型:
byte, short, int, long 的默认初始化值都为0
浮点类型:
float, double 的默认初始化值都为0。0
布尔类型:
boolean的默认初始化值为false
字符类型:
char默认初始化值为 “\u0000”,char在内存中是占两个字节,是16个二进制位。\u0000每个0代表16进制的0,那么四个0就是代表16个二进制位。
一个字节代表8个二进制位,那么两个字节,就代表16个二进制位。'\u0000'每个0代表16进制的0,那么四个0就是代表16个二进制位。
char在内存中占两个字节
代表16个二进制位, 两个字节代表16个二进制位。
一个字节代表8个二进制位,那么两个字节就代表16个二进制位。
\u0000:
每个0代表16进制的0,那么四个0就代表16个二进制位。
两个字节就代表16个二进制位,那么四个0代表16个二进制位。
char:就代表16个二进制位。
\u0000`:就代表16个二进制位 = 四个0就代表16个二进制位。
每个0就代表16个进制的二进制数。1个0就代表4位,16进制是4位代表一位的,4个就代表16个二进制数。
16个二进制位: 0000
一个就代表4个二进制位,那么4个就代表16个二进制位。
数组元素如果是引用数据类型为类,接口和数组,那么数组元素的初始化值是null。
注意:静态初始化和动态初始化不能同时用,不要在进行数组初始化值是,既要分配数组元素初始化值,还要给定数组的长度,千万不要,知道吗!
枪
枪中的弹夹,子弹是一颗一颗地压进去的,第一颗压进的子弹是最后打出来的,最后一颗的子弹先发射出来。所以java中的方法就想弹夹一样,而主方法,是先进入内存的,虚拟机调用主方法,程序运行起来,首先进入内存的,进入栈的,是主方法。
主方法就像子弹一样,放入到栈低,压进栈,压栈。主方法直接压入栈底,运行完之后会弹出去,就叫弹栈。栈是先进后出。主方法压进栈。方法里的局部变量,类型为数组类型。
代码案例:
package com。dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // int x = 12; // x就是局部变量 int[] arr = new int=[3]; // 动态初始化,创建3块连续的空间 // 方法里的局部变量 } }
在栈中存放主方法,主方法内有局部变量,这个局部变量为数组类型:
int[] arr;
然后在堆中是数组类型new出来的值。
内存分析案例:
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // int x = 12; // x就是局部变量 int[] arr = new int[3]; // 动态初始化,创建3块连续的空间 // 方法里的局部变量 arr[0] = 10; arr[1] = 20; system.out.println(arr[0]); system.out.println(arr[1]); } }
制作内存图:
地址值是赋予给arr,只是通过地址找到实体的。
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr1 = new int[3]; // 创建数组长度为3 int[] arr2 = new int[3]; system.out.println(arr1); // 打印数组的地址值 system.out.println(arr2); arr1[0] = 10; // 给第一个数组中的第一个元素赋值 arr2[1] = 20; // 给第二个数组中的第二个元素赋值 system.out.println(arr1[0]); system.out.println(arr1[1]); system.out.println(arr1[2]); system.out.println("-----------"); system.out.println(arr2[0]); system.out.println(arr2[1]); system.out.println(arr2[2]); } }
制作内存图:
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr1 = new int[3]; int[] arr2 = new int[5]; int[] arr3 = arr2; system.out.println(arr1); system.out.println(arr2); system.out.println(arr3); arr1[0] = 10; arr1[1] = 20; arr2[1] = 30; arr3[1] = 40; arr3[2] = 50; system.out.println(arr1[0]); system.out.println(arr1[1]); system.out.println(arr1[2]); system.out.println("--------------"); system.out.println(arr2[0]); system.out.println(arr2[1]); system.out.println(arr2[2]); system.out.println(arr2[3]); system.out.println(arr2[4]); system.out.println("--------------"); system.out.println(arr3[0]); system.out.println(arr3[1]); system.out.println(arr3[2]); system.out.println(arr3[3]); system.out.println(arr3[4]); } }
结果:
制作内存图:
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 数据类型[] 数组名=new 数据类型[]{元素1,元素2,...}; // int[] arr = new int[] {1,23,45,67,28}; // int[] arr2 = {2,35,6,12}; // 静态初始化的简写形式 // int[] arr; //声明数组引用 // arr = new int[] {11,22,33,44}; // 可以不同行 // int [] arr2; // arr2 = {23,43,55}; // 简写形式声明和赋值必须在同一行 // int[] arr = new int[3]{23,22,1}; //会报错,不允许动静结合 // 应该写成 int[] arr = new int[3]; 为动态初始化 // int[] arr = new int[]{23,44,2}; 为静态初始化 } } package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 数据类型[] 数组名=new 数据类型[]{元素1,元素2,...}; // int[] arr = new int[] {1,23,45,67,28}; // int[] arr2 = {2,35,6,12}; // 静态初始化的简写形式 int[] arr = {12,23,34}; system.out.println(arr); system.out.println(arr[0]); } }
制作内存图:
数组中的异常问题:
程序员写程序不能保证自己写的代码是正确的,总会出现一些错误,这时我们要学会调式这些代码程序保证可以正常的运行。
数组索引越界异常
arrayindexoutofboundsexception,指你访问的索引不存在。
int arr = {1,34,234}; system.out.println(arr[23]);
空指针异常
nullpointerexception,指数组已经不在指向堆内存了,而你还用数组名去访问元素。
int[] arr = {1,2,3}; arr = null; system.out.println(arr[0]); package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr = new int[5]; system.out.println(arr[5]); // 当访问数组中不存在的索引,就会出现索引越界异常. } }
结果图:
当访问数组中不存在的索引的时候就会导致数组越界异常。
同理
system.out.println(arr[-1]); 同样导致数组越界异常。
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr = new int[5]; // system.out.println(arr[5]); arr = null; system.out.println(arr[0]); // 当数组引用赋值为null,在去调用数组中的元素就会出现空指针异常. } }
结果图片:
数组的遍历:
循环数组中的每个数组元素。
使用foreach循环,这种循环遍历数组是非常方便的,foreach循环的格式如下:
for (type variablename : array ){ // 访问每个元素 }
代码案例:
public class foreachtest { public static void main(string[] args){ string[] names = { “dashu”, “dashucoding”}; // 使用foreach循环遍历数组中的每个元素 for(string name : names){ system.out.println(name); } } }
代码案例:
package com.dashucoding;/* * 数组的遍历:依次输出数组中的每个元素 * 数组的属性:arr.length数组的长度 * 数组的最大索引:arr.length-1; * */public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr = {11,22,33,44,55}; /* system.out.println(arr[0]); system.out.println(arr[1]); system.out.println(arr[2]); system.out.println(arr[3]); system.out.println(arr[4]);*/ for(int i = 0; i < arr.length; i++) { system.out.println(arr[i]); } system.out.println("---------"); // arr.length 代表数组的长度 system.out.println(arr.length); system.out.println("---------"); int[] arr2 = {1,2,3}; print(arr2); } /* * 遍历数组的方法 * 返回值类型为void * 参数列表int[] arr * */ private static void print(int[] arr) { // todo auto-generated method stub for(int i = 0;i<arr.length;i++) { system.out.println(arr[i]); } } }
结果图片:
最大值
代码案例:
package com.dashucoding;/* * 数组 * 如何获取数组的最大值 * */public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr = {23,34,12,33}; int max = getmax(arr); system.out.println(max); } /* * 获取数组最大值 * 返回值类型为int * 参数列表为int[] arr * */ public static int getmax(int[] arr) { int max = arr[0]; for (int i = 1; i < arr.length; i++) { // 从数组的第二个元素开始遍历 if(max < arr[i]) { // 如果max记录的值小于数组中的元素,就max记录记录最大的 max = arr[i]; } } return max; } }
结果图:
分析制图:
数组的操作反转:
操作反转,就是前后倒置
package com.dashucoding;/* * 数组 * 如何获取数组的最大值 * */public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr = {22,33,44,55}; reversearray(arr); print(arr); } /* * 数组元素的反转 * 返回值类型void * 明确参数列表int[] arr * */ public static void reversearray(int[] arr) { for(int i=0; i < arr.length / 2; i++) { // arr[0] 第一个 和 arr[arr.length-1-0] 最后一个 交换 // arr[1] 和 arr[arr.length-1-1] 交换 // arr[2] 和 arr[arr.length-1-2] 交换 // ... /*int temp = arr[0]; arr[0] = arr[arr.length-1]; arr[arr.length-1] = temp;*/ int temp = arr[i]; arr[i] = arr[arr.length-1-i]; arr[arr.length-1-i] = temp; } } /* * 数组遍历 * 明确返回值类型void * 明确参数列表int[] arr * */ public static void print(int[] arr) { for(int i = 0; i < arr.length; i++) { system.out.print(arr[i] + " "); } } }
结果图片:
根据键盘录入索引,查找对应的星期:
代码案例:
package com.dashucoding; import java.util.scanner; /* * 数组 * 如何进行数组查表(根据键盘录入索引,查找对应的星期) * */public class demoarray { public static void main(string[] args) { // todo auto-generated method stub system.out.println("星期" + getweek(2)); system.out.println("----------"); // 键盘录入 scanner sc = new scanner(system.in); system.out.println("请输入对应的星期范围,对应1至7"); int week = sc.nextint(); system.out.println("星期" + getweek(week)); } /* * 根据索引返回对应的星期 * 返回值的类型char * 能存储中文的char * 参数列表int week * 通过索引获取数组中的元素 * */ public static char getweek(int week) { char[] arr = {' ','一','二','三','四','五','六','日'}; // 定义一张星期表 return arr[week]; // 通过索引获取数组中的元素 } }
数组元素查找:
package com.dashucoding; import java.util.scanner; /* * 数组 * 数组元素查找 * 查找指定元素第一次在数组中出现的索引 * */public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[] arr = {11,22,33,44,55}; int index = getindex(arr,22); system.out.println(index); system.out.println("----------"); int index2 = getindex(arr,10); system.out.println(index2); } /* * 查找元素索引 * 返回值类型int * 参数列表int[] arr, 要查找的值int value * */ public static int getindex(int[] arr, int value) { for(int i = 0; i < arr.length; i++) { // 数组的遍历 if(arr[i] == value) { // 如果数组中的元素与查找元素匹配,就是这个元素 return i; // 返回索引 } } // 如果没有查到,没找到返回给你一个-1,如果返回值为-1,就知道没在数组中找到 return -1; } }
结果图片:
二维数组的格式:
int[][] arr = new int[3][2];
表示二维数组的格式:
数据类型 数组名[][] = new 数据类型[m][n]; 数据类型[] 数组名[] = new 数据类型[m][n];
// 建议这么写 int[][] arr = new int[3][2]; // 一维数组 int[] x; // 二维数组int[] x,y[];int[] y[];
二维数组案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub /* * 二维数组 * 二维数组中有3个一维数组 * 每个一维数组中有2个元素 * */ int[][] arr = new int[3][2]; // 打印二维数组 system.out.println(arr); // 打印二维数组中的第一个一维数组 system.out.println(arr[0]); // 打印二维数组中的第一个一维数组的第一个元素 system.out.println(arr[0][0]); // 打印结果 /* * [[i@7852e922 // 二维数组的地制值 * [i@4e25154f // 一维数组的地址值 * 0 // 元素值 * */ } }
结果图片:
二维数组:
package com.dashucoding; import java.util.scanner; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub int[][] arr = new int[3][2]; system.out.println(arr); system.out.println(arr[0]); system.out.println(arr[0][0]); } }
内存分析:
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 二维数组,二维数组中有3个一维数组,三个一维数组都没有被赋值 int[][] arr = new int[3][]; // 打印二维数组中的三个一维数组 system.out.println(arr[0]); system.out.println(arr[1]); system.out.println(arr[2]); arr[0] = new int[3]; // 第一个一维数组中存储三个int值 arr[1] = new int[5]; // 第二个一维数组中存储五个int值 system.out.println("-----"); // 打印二维数组中的三个一维数组 system.out.println(arr[0]); system.out.println(arr[1]); system.out.println(arr[2]); } }
结果图片:
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 二维数组,二维数组中有3个一维数组,三个一维数组都没有被赋值 int[][] arr = new int[3][]; // 打印二维数组中的三个一维数组 system.out.println(arr[0]); system.out.println(arr[1]); system.out.println(arr[2]); } }
分析内存图:
二维数组格式:
int[][] arr = { {1,2,3}, {4,5}, {6,7,8,9} };
代码案例:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 二维数组 int[][] arr = { {1,2,3}, {4,5}, {6,7,8,9} }; system.out.println(arr); //二维数组的地址值 system.out.println(arr[0]); //一维数组的地址值 system.out.println(arr[0][0]); //元素 } }
结果图:
内存分析图:
二维数据的遍历:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 二维数组的遍历 int[][] arr = { {1,2,3}, {4,5}, {6,7,8,9} }; 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(); } } }
结果图:
二维数组的求和:
package com.dashucoding; public class demoarray { public static void main(string[] args) { // todo auto-generated method stub // 二维数组求和 int[][] arr = { {1,2,3}, {4,5,6}, {7,8,9} }; int sum = 0; for(int i = 0; i < arr.length; i++) { // 获取每个一维数组 for(int j = 0; j < arr[i].length; j++) { //获取每个一维数组 sum = sum + arr[i][j]; } } system.out.println(sum); } }
结果图:
基本数据类型的值传递,不会改变原值,因为调用后会弹栈,局部变量就会随之消失,而引用数据类型的值传递,会改变原值,因为使用方法弹栈,但是堆内存数组对象还在,可以通过地址继承访问。
数组的综合应用
代码案例:
// 打印数组public static void printarray(int[] arr){ for(int x=0;x<arr.length;x++) { if(x!=arr.length-1){ system.out.print(arr[x]+","); }else{ system.out.print(arr[x]); } } }
数组转字符串:
// 数组转换成为字符串// 结果返还为字符串,参数为数组public static string tostring (int[] arr){ // 定义字符串变量 string temp = "["; for(int x = 0; x<arr.length; x++){ // 判断是否为最后一位元素 if(x != arr.length - 1){ temp = temp + arr[x] + ","; }else{ temp = temp + arr[x] + "]"; } } } public static string getweek(int num){ string[] weeks = { "1", "2", "3", "4", "5", "6", "7" }; if(num>7 || num<1){ return num + "没有对应的星期"; } return weeks[num]; }
选择排序
选择排序是第一个人和后续排序的人进行比较,若第一个人大于第二个人,就进行交换,那么这时第一人就是最小的,然后这时的第一个人和第三个人进行比较,若这时的第一个人大于第三个人,就进行交换位置,这时第一个人又换人了,也变得更小了,就这样,把剩下的人以这种方法进行比较,直到最后,第一轮结束,在第一位的就是最小的值。
这种就是排序算法,比如有6个人,第一轮要进行5次比较。小的值往前跑嘛。
//第一轮 for(int index=1;index<arr.length;index++) { if(arr[0]>arr[index]) { int temp = arr[0]; arr[0] = arr[index]; arr[index] = temp; } } print(arr); //第二轮 for(int index=2;index<arr.length;index++) { if(arr[1]>arr[index]) { int temp = arr[1]; arr[1] = arr[index]; arr[index] = temp; } } print(arr); //第三轮 for(int index=3;index<arr.length;index++) { if(arr[2]>arr[index]) { int temp = arr[2]; arr[2] = arr[index]; arr[index] = temp; } } print(arr); //第四轮 for(int index=4;index<arr.length;index++) { if(arr[3]>arr[index]) { int temp = arr[3]; arr[3] = arr[index]; arr[index] = temp; } } print(arr); //第五轮 for(int index=5;index<arr.length;index++) { if(arr[4]>arr[index]) { int temp = arr[4]; arr[3] = arr[index]; arr[index] = temp; } } print(arr); //第六轮没有,我们arr.length=6举例 //int index = 6;index<arr.length; false
优化:
public static void selectionsort(int[] arr) { for(int count=1;count<arr.length;count++) { for(int index=count;index<arr.length;index++) { if(arr[count-1]>arr[index]) { int temp = arr[count-1]; arr[count-1] = arr[index]; arr[index] = temp; } } } for(int x = 0;x<arr.length-1;x++) { for(int y=x+1;y<arr.length;y++){ if(arr[x]>arr[y]){ int temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } } }
冒泡排序
为什么这个排序要叫冒泡呢?为什么不叫其他名词呢?
其实这个取名是根据排序算法的基本思路命名的,见名知意,冒泡排序,就是想泡泡在水里一样,在水里大的泡泡先浮出水面,就是大的先排出来,最小的最慢排出。
冒泡排序,是对排序的各个元素从头到尾依次进行相邻的大小比较,比如你是队长,在你的面前有一排人,你要将其进行排序,依次按照从小到大排序。
怎么理解最大的值被排除,你是队长,你对面前的一群人看不惯,进行排序,从左到右开始,第一个和第二个进行比较,大的那个就被挑出来,与第三个进行比较,接下来就是依次按照这个方法比较,就能把那个最大的值,最高的给挑出来不是,这就是第一轮的比较。
接下来,最大的就不用跟他比较了,上面所述,在排序时,你面前的人,是不能乱动的,一旦比较哪个大,两者就换位,如果第一比第二个小,就是第二个大时,两者不用换位,第二个就与第三个进行比较。
依照这个方法,两两比较,大的都被排到了最后,那么一旦排完,是不是都依照从小到大,(从低到高)的顺序在你面前排好了。
代码示例
我们用索引下标来解释
//第一轮 for(int index=0;index < arr.length-1; index++){ //相邻两个比较 if(arr[index] > arr[index+1]){ int temp = arr[index]; arr[index] = arr[index+1]; arr[index+1] = temp; } } print(arr); for(int index=0;index < arr.length-2;index++){ //这里arr.length-2,为什么比上一次多减了1呢? //因为第一轮,把最大的排出来了,就不用比较了,少了一个人 if(arr[index] > arr[index+1]){ int temp = arr[index]; arr[index] = arr[index+1]; arr[index+1] = temp; } } print(arr); for(int index=0;index < arr.length-3;index++){ if(arr[index]>arr[index+1]){ int temp = arr[index]; arr[index] = arr[index+1]; arr[index+1] = temp; } } print(arr);
优化:
for(int num=1;num<arr.length;num++){ for(int index=0;index<arr.length-num;index++){ if(arr[index]>arr[index+1]){ int temp = arr[index]; arr[index] = arr[index+1]; arr[index+1] = temp; } } } for(int x=0;x<arr.length-1;x++){ for(int y=0;y<arr.length-1-x;y++){ if(arr[y]>arr[y+1]){ int temp = arr[y]; arr[y] = arrp[y+1]; arr[y+1] = temp; } } }
二分查找,折半查找
什么是二分查找,折半查找呢?就是我说一个数,你来猜,你答一个数,我说大了,或小了,直到找到为止。
public static int searchkey(int[] arr, int key){ for(int x=0;x<arr.length;x++){ if(arr[x] == key){ rerurn x; } return -1; } }
二分
public static int binarysearch(int[] arr, int key){ int max,min,mid; min = 0; max = arr.length - 1; mid = (max+min)>>1; while(arr[mid] != key){ if(key>arr[mid]){ min = mid + 1; }else if(key<arr[mid]) max = mid - 1; mid = (max+min)>>1; } return mid; } } public static int binarysearch(int[] arr, int key){ int max, min , mid; min = 0; max = arr.length - 1; while(min <= max){ mid = (min+max)>>1; if(key>arr[mid]){ min = mid + 1; }else if(key < arr[mid]) max = mid - 1; } else { return mid; } return -1; }
二维数组
格式:
int[][] arr = new int[2][3]; int[][] arr = { {3,5,6}, {33,44,66}, {23,21,6} }; for(int x=0; x<arr.length; x++){ for(int y=0; y<arr[x].length; y++){ sum += arr[x][y]; } } public static void revese(int[] arr){ for(int start=0, end = arr.length-1; start<end; start++,end--){ swap(arr,start,end); } } public static void swap(int[] arr, int a, int b){ int temp=arr[a]; arr[a] = arr[b]; arr[b] = temp; }
本章小结
本章主要介绍了数组的定义,初始化,使用等基本知识,结合了大量的分析内存图用来分析数组在内存中的运行机制,数组的引用变量和数组直接的关系,大量讲解多维数组的实质性问题,文章中给出了多种代码案例来展示数组的运用扩展。
结言
好了,欢迎在留言区留言,与大家分享你的经验和心得。
感谢你学习今天的内容,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给更多的朋友,感谢。
达叔小生:往后余生,唯独有你
you and me, we are family !
90后帅气小伙,良好的开发习惯;独立思考的能力;主动并且善于沟通
简书博客: 达叔小生
结语
- 下面我将继续对 其他知识 深入讲解 ,有兴趣可以继续关注
- 小礼物走一走 or 点赞
上一篇: 我很高兴我没有吞下你!
下一篇: shell脚本学习笔记
推荐阅读