1. 数组的基本使用方法
1.1 什么是数组?
. 数组是一种数据结构, 用来创建存储同一类型值的集合。通过一个整型下标可以访问数组中的每一个值。
.例如, 如果假设 a 是一个整型数组, a[i] 就是数组中下标为 i 的整数。(相当于在系统空间中开辟了一块 连续的 ‘房间’, 下标 i 就相当于对应房间的钥匙,不同的 i(钥匙)都对应着不同的房间)
什么是数据结构:
**简单来说:就是把一堆数字保存起来的结构就是数据结构 **
数据结构关心的是如何高效的读写数据
注释:在 Java 中, 数组中所有的变量必须是 相同类型
** 在声明数组变量时, 需要指出数组类型 ( 数据元素类型紧跟 [ ]) 和数组变量的名字。下面声明了整型数组 a**
** int[ ] a;**
不过, 这条语句只声明了变量 a, 并没有将 a 初始化为一个真正的数组。应该使用 new 运算符创建数组。 int[ ] a = new int[100];
** 这条语句创建了一个可以存储 100 个整数的数组。数组长度不要求是 常量: newint[n] 会创建 一个长度为 n 的数组。(也可以是我们自己创建的变量 n 。跟C语言不一样,C语言规定了必须是 常量)**
**注释:可以使用下面 两种形式 声明数组 **
** int[ ] a; 或 int a[ ];**
大多数 Java 应用程序员喜欢使用第一种风格, 因为它将类型 int[ ] ( 整型数组)与变 量名分开了。
1.2 创建数组
基本格式:
** 动态初始化: 标准写法就是这两种,动态的。**
1. 数据类型[ ] 数组名称 = new 数据类型 [ N ] ; //创建可以存储 N 个值的 数组
2. 数据类型[ ] 数组名称 = new 数据类型 [ ] { 初始化数据 }; // 自定义内容
** 静态初始化**
3. 数据类型[ ] 数组名称 = { 初始化数据 }; // 上面第二种方法的简写,本质一样。
数组的静态初始化:其实就是****语法糖,javac编译之后,任然是动态初始化,两者没有任何区别。
语法糖:只存在编译期之前的语法,编译器为了方便程序员简化写法
证明两者的一样: 可以使用Idea自带的控制台。
方法:在想编译的java文件,右击,找到 Open ln, Explorer。然后javac 文件名字 编译后会生成 class文件。点击查看即可。
代码示例:
public class Test_4_6 {
public static void main(String[] args) {
// 动态初始化
int[] arr1 = new int[10]; // 开辟了可以存储 10个 整数的数组
int[] arr2 = new int[]{1,2,3}; //自定义数组里面的内容
// 静态初始化
int[] arr3 = {1,2,3};
}
}
注意事项:
1. 初始化后 数组里元素个数就是初始值的个数
2. 不能既 指定 开辟空间的数,同时又初始化元素内容。
就是只能 创建一个数组,并指定个数 ; 或者 创建一个数组,进行初始化赋值
例如我想开辟 10个空间大小,且初始化前三个空间的内容。
** 注释:(可以先创建数组,然后再进行赋值语句)**
3.这个数组的下标从 0 ~ 9 (不是 1 ~ 10 )。一旦创建了数组,就可以给数组里的元素赋值。
3.1 那么我们应该如何赋值呢?
基本格式:
** 使用数组名称[要访问的元素相较于第一个元素的偏移量].**
或者这么说:
使用数组名称[元素的索引]
例如 我们用循环赋值:
** 4. 静态初始化 对比 动态初始化 是一种 简化书写形式。**
** 在使用这种语句时,不需要调用 new。 如: int[ ] arr3 = {1,2,3};**
** 5. 创建一个数组时,如果没有指定其 初始化的内容,都会自动初始化。**
** 创建一个数字数组时, 所有元素都会初始化为 0。**
** 创建一个boolean 数组的元素会初始化为false。**
** 创建一个 对象数组 的元素则初始化为一个特殊值 null。(后面会讲)**
** 这表示这些元素(还)未存放任何对象。**
1.3 获取数组的长度
想获得数组中的元素个数,可以使用 数组名称.length。
代码示例:
**格式是: 数组名 + .length **
注意事项:
1. 使用 [ ] 按下标 找到数组元素位置. 需要注意, 下标从 0 开始计数(如:第 5 个元素,下标则是 4)
2. 使用 [ ] 操作既能读取数据, 也能修改数据.
3. 读取数据决定不能 越界访问。
下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现
“ array index out of bounds” 异常而终止执行
4. 一旦创建了的数组,就不能再改变它的大小了(可以改变元素内容)。
补充:如果想在运行过程中扩展数组的大小, 就应该使用另一种数据结构—数组列表,在后面会介绍到。
1.4 for each 循环
什么是遍历数组?
所谓 "遍历" 是指将数组中的所有元素都访问一遍, 不重不漏. (通常需要搭配循环语句.)
** 例如:打印数组里所有元素:**
int[] arr = new int[10];
//赋值操作
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
//打印数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
** 引出:for each 循环**
** 数组的越界是很严重的,每次设计程序的时候都需要小心翼翼,很麻烦。**
** 而Java 有一种功能很强的循环结构, 可以用来依次处理数组中的每个元素(其他类型的元 素集合亦可)而不必为指定下标值而分心。**
这种增强的 for 循环的语句格式为:
for ( variable : collection ){
** statement;**
}
功能: 定义一个变量用于暂存集合中的每一个元素, 并执行相应的语句(当然,也可以是语句块)。
variable:这里面写 变量类型 + 自定义一个变量名(这个名字是自定义的,等会要用到)
collection :这里写 要遍历数组的 数组名
statement :需要执行的语句(语句块)
代码示例1:打印数组里所有元素
public static void main(String[] args) {
int[] arr = {1, 2, 3};
printArray(arr);
}
public static void printArray(int[] a) {
for (int x : a) {
System.out.println(x);
}
}
int x 中的 x,是一个变量,用来保存从数组中拷贝到的值,
比如说第一次循环,x的值就等于a【0】
第二次循环, x的值就等于 a【1】以此类推,
所以 x 只是拷贝值,修改它并不会影响原来的数组内容。
提醒:int[ ] 是类型,表示整形数组,当在方法中,可以用 来接收 数组。
*小知识:***int[ ] 类型 **属于引用数据类型,具体来说,就是整型数组的引用
代码示例2:打印数组里所有元素
public class Test_4_6 {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
for (int x:
arr) {
System.out.println(x);
}
}
}
解读:
1. 两个代码差不多,只是 格式不同,使用的地方不同。一个在mian函数里面执行,一个在 方法 里执行。
2.功能是:打印数组 arr 的每一个元素,一个元素占一行。
** 这个循环应该读作“ 循环 a 中的每一个元素”**
结论:
1. 无论是 普通的循环,还是 加强的 for each 都能实现目的,各有各的优点。
2. for each循环 只能用于遍历数组的情况,如果不想遍历整个数组,还是要用平常的for循环
3. 如果是需要遍历整个数组的情况下,for each显得更加 简洁和方便,不需要使用下标值(不必为下标的起始值和终止值而操心)
附加知识的:****如果想要打印数组中的所以值,Java有个快捷的办法。
** 即利用 Arrays 类的 toString 方法。需要引头文件( **import java.util.Arrays; )
** 调用 Arrays.toString(arr), 返回一个包含数组元素的字符串,这些元素被放置在括号内, 并 用逗号分隔.**
** 可以用 String引用类型接受:**
** 或者直接输出:**
示例代码:
1.5 匿名数组
匿名数组的表示方法:
new int[ ]{1, 2, 3, 4, 5};
匿名函数的功能有:使用这种语法形式可以在不创建新变量的情况下重新初始化一个数组。相当于在一个已有的数组基础上,重新对它进行定义!
使用场景:
//先创建一个已存在的数组, arr
int[] arr = new int[]{0,1,2,3,4};
//打印数组中的每个元素
for (int x :
arr) {
System.out.println(x);
}
System.out.println("-------------------");
//数组大小是它初始化的元素个数
System.out.println(arr.length);
运行:
**现在使用匿名数组对这个数组进行初始化,定义为 {6,7,8, 9} **
核心是这块:
**对比之前的结果代码: **
public class Test_4_8 {
public static void main(String[] args) {
//先创建一个已存在的数组, arr
int[] arr = new int[]{0,1,2,3,4};
//打印数组中的每个元素
for (int x :
arr) {
System.out.println(x);
}
System.out.println("----没改之前-------");
//数组大小是它初始化的元素个数
System.out.println("长度 " + arr.length);
System.out.println("-------------------");
arr = new int[]{6,7,8,9};
for (int x :
arr) {
System.out.println(x);
}
System.out.println("-------改了之后------");
System.out.println("长度 " + arr.length);
}
}
运行解放 + 分析:
** 发现:**
不仅仅数组内容被 匿名数组 更改了,连数组原本的长度也变了。
** 结论:**
对一个数组进行 匿名数组 赋值时,会彻底改变这个数组,所以内容 + 长度都会是 匿名数组的参数。
注释:
在 Java 中, 允许数组长度为 0。在编写一个结果为数组的方法时, 如果碰巧结果 为空, 则这种语法形式就显得非常有用。此时可以创建一个长度为 0 的数组
注意, 数组长度为 0 与 null 不同。
1.6 数组拷贝
** 在 Java 中,允许将一个数组变量拷贝给 另一个数组变量。**
例如:让str数组里面的第一个元素变成 arr数组里面第二个元素
public class Test_4_8 {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
int[] str = new int[]{6,7,8,9,10};
System.out.println(str[0]);
str[0] = arr[1];
System.out.println(str[0]);
}
}
运行结果:
** 一个个赋值太麻烦了,如果希望将 一个数组的所有值拷贝到一个新的数组中去, 就要使用 Arrays 类的 copyOf方法 (需要头文件,**import java.util.Arrays; )
注释:
1. 第 一 个参数是要拷贝的数组名称
2. 第 二 个参数是新数组的长度。这个方法通常用来增加数组的大小
特殊注释: 如果数组元素是数值型,那么多余的元素将被赋值为 0 ; 如果数组元素是布尔型,则将赋值 为 false。相反,如果长度小于原始数组的长度,则只拷贝最前面的数据元素。(copyOf方法 )会改变新数组的大小
案例代码:
import java.util.Arrays;
public class Test_4_8 {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
int[] str = new int[]{6,7,8};
for (int x :
str) {
System.out.println(x);
}
System.out.println("长度 = " + str.length);
System.out.println("----------------------------");
str = Arrays.copyOf(arr, arr.length + 2);
for (int x :
str) {
System.out.println(x);
}
System.out.println("----------------------------");
System.out.println("长度 = " + str.length);
}
}
运行结果:
** 提醒一下:**
** Java 中的 [ ] 运算符被预定义为检查数组边界,而且没有指针运算, 即不能通过 a 加 1 得到数组的下一个元素。**
2.数组作为方法的参数
2.1理解引用类型(重点/难点)
假设我们想参加一个方法,让它交换两个变量的值。
示例代码:
public class Test_4_10 {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("-------修改之后---------");
exchange(a, b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
public static void exchange(int a, int b){
int tmp = a;
a = b;
b = tmp;
}
}
运行结果: 发现 a 和 b 的值并没有得到修改
** 那我们试试另一个办法:参数传数组类型**
示例代码:
// 交换两个变量的值
public class Test_4_10 {
public static void main(String[] args) {
int a = 10;
int b = 20;
int[] arr = {a, b};
System.out.println("a = " + arr[0]);
System.out.println("b = " + arr[1]);
System.out.println("-------修改之后---------");
//exchange(a, b);
exchange(arr);
System.out.println("a = " + arr[0]);
System.out.println("b = " + arr[1]);
}
public static void exchange(int[] arr){
int tmp = arr[0];
arr[0] = arr[1];
arr[1] = tmp;
}
}
运行结果: 发现成功交换了两个变量的值。
在函数内部修改数组内容, 函数外部也发生改变. 此时数组名 arr 是一个 "引用" .
当传参的时候, 是按照引用传参.
为什么用数组作为传参就能成功呢?
这里我们要先从内存开始说起.
**如何理解内存? **
**内存就是指我们熟悉的 "电脑的运行内存". 内存可以直观的理解成一个宿舍楼. **
**有一个长长的大走廊, 上面有很多房间. 每个房间的大小是 1 Byte (如果计算机有 8G 内存, 则相当于有 80亿 个这样的房间). **
每个房间上面又有一个门牌号, 这个门牌号就称为 地址
那么啥又是引用?
引用相当于一个 "别名", 也可以理解成一个指针.(C语言)
创建一个引用只是相当于创建了一个很小的变量, 这个变量保存了一个整数, 这个整数表示内存中的一个地址.
知识补充:
注释:
对于数组对象来说,数组引用实际上就是保存了数组的首元素地址。
举例说明:
比如说执行 int[] arr = new int[]{1, 2, 3}
相当于在 堆区 上开辟了连续的三个空间来保存 1, 2, 3
**又创建了一个 int[] 变量, 这个变量是一个引用类型, **
里面只保存了一个整数(数组的起始内存地址)
**我们在对堆区的范围靠的是arr里面保存的地址。这样才能修改方法外面的参数。而之前传入的如: int a ,int b,都是传值,是 拷贝值,影响不了外面的参数。 **
** 结论:**
1. ** 所谓的 "引用" 本质上只是存了一个地址. Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实 只是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大)**
注释:传址(地址)要远远优于 传值(数值)
2. 要操作堆中的对象,必须通过引用来进行,必须知道这个对象的名字(也就是地址)才能操作。
2.2 认识 null
null 在 Java 中表示 "空引用" , 也就是一个无效的引用.
简单了解一下:
null 的作用类似于 C 语言中的 NULL (空指针), 都是表示一个无效的内存位置. 因此不能对这个内存进行任何读写操 作. 一旦尝试读写, 就会抛出 NullPointerException.
注意: Java 中并没有约定 null 和 0 号地址的内存有任何关联,两者并不能等同。
2.3 初识 JVM 内存区域划分(重点)
属于额外知识点,不需要一定弄懂,大概先知道有这么个东西就行
一个宿舍楼会划分成几个不同的区域: 大一学生, 大二学生... 计算机专业学生, 通信专业学生.... 内存也是类似, 这个大走廊被分成很多部分, 每个区域存放不同的数据.
JVM 的内存被划分成了几个区域, 如图所示:
** 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址.**
虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] arr 这样的存储地 址的引用就是在这里保存.
本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局 部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.
**堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} ) **
**方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数 据. 方法编译出的的字节码就是保存在这个区域. **
运行时常量池(Runtime Constant Pool): 是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从 JDK 1.7 开始, 运行时常量池在堆上).
**Native 方法: **
**JVM 是一个基于 C++ 实现的程序. 在 Java 程序执行过程中, 本质上也需要调用 C++ 提供的一些函数进行 和 操作系统底层进行一些交互. **
因此在 Java 开发中也会调用到一些 C++ 实现的函数. 这里的 Native 方法就是指这些 C++ 实现的, 再由 Java 来调用的函数.
**发现: 在上面的图中, 程序计数器, 虚拟机栈, 本地方法栈被很多个原谅色的, 名叫 Thread(线程) 的方框圈起来了, 并且存在很多份. **
而 堆, 方法区, 运行时常量池, 只有一份. (关于线程, 这是我们后面重点讲解的内容).
总结一
学习了内存中的两个重要区域, 栈区 和 堆区
栈区:
方法的调用就是在栈区进行的,每个方法的调用过程,就是一个栈帧的入栈以及出栈过程。
** 方法中的局部变量和形参都在栈中存储。
当方法调用结束出栈时,临时变量都会被销毁。**"栈”-先进后出的结构,LIFO
注释:我们平常写的main也算方法,是主方法。在栈区开辟空间。堆区:
JVM的另一块内存区域称为"堆区",所有对象都在堆区存储 数组对象,类的实例化对象,接口的对象。
思路拓展1:我们平常说的,main方法里面的进场全部结束了,那么这个程序就全部结束了。
原因是因为,栈 先进后出的 特点。main方法是最开始执行的程序,是入口。连它都结束被销毁了,当然所有内容都结束了。
思路拓展2: 比如说我在 子方法 里用new开辟了一个 数组空间,如图中所示。
**在swapArr方法调用结束了,里面的 arr等所有栈中开辟的空间会被销毁,但在堆中申请的空间却不会因此而消失,反而会一直存在,除非特意返回这块空间的地址,不然所有人都找不到这块空间。 **
假设我们一直申请申请,在地址销毁。堆空间会不会被堆满?答案是不会!
解释:
**总结一句话,堆中的销毁不需要程序员自己担心,JVM会自行处理。 **
4.数组练习(习题)
4.1 数组转字符串
//1. 数组转字符串
/**
* 模拟实现 Arrays.toString方法的功能
* 把一个数组转换成 字符串 并返回
*/
import java.util.Arrays;
public class Test_4_10_ZY {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
String sc = Arrays.toString(arr);
System.out.println(sc);//[1, 2, 3, 4, 5]
System.out.println();
String sc2 = MY_toString(arr);
System.out.println(sc2);
}
private static String MY_toString(int[] arr) {
String sc = "[";
for (int i = 0; i < arr.length; i++) {
sc += arr[i];
if(i != arr.length - 1)
sc += ", ";
}
sc += "]";
return sc;
}
}
4.2 数组拷贝
//2. 数组拷贝
/**
* 模拟实现 Arrasy.copyOf
* 深层次拷贝数组中每一个元素,并返回。
*/
import java.util.Arrays;
public class Test_4_10_ZY {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
int[] cop1 = Arrays.copyOf(arr, arr.length);
System.out.println(Arrays.toString(cop1));
System.out.println("------对比--------");
int[] cop2 = MY_copyOf(arr, arr.length);
System.out.println(Arrays.toString(cop2));
}
private static int[] MY_copyOf(int[] arr, int length) {
int[] str = new int[length];
for (int i = 0; i < length; i++) {
str[i] = arr[i];
}
return str;
}
}
//3. 找数组中的最大元素.
//3. 找数组中的最大元素.
/**
* 给定一个整型数组,
* 找到其中的最大元素 (找最小元素同理)
*/
public class Test_4_10_ZY {
public static void main(String[] args) {
int[] arr = new int[]{1,2,6,9,5};
System.out.println(max(arr));
}
public static int max(int[] arr){
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if(max < arr[i])
max = arr[i];
}
return max;
}
}
** 4 求数组中元素的平均值**
//4 求数组中元素的平均值
/**
* 求数组里面所有元素的返回值
* 返回类型是 double 浮点数
*/
public class Test_4_10_ZY {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
System.out.println(average(arr));
}
public static double average(int[] arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return (double)sum / (double)arr.length;
}
}
//5 查找数组中指定元素(顺序查找)
/**
* 给定一个数组, 再给定一个元素,
* 找出该元素在数组中的位置,并返回其下标.
*/
//public class Test_4_10_ZY {
// public static void main(String[] args) {
//
// int[] arr = new int[]{1,2,3,4,5};
// int rep = find(arr, 8);
// if(rep == -1){
// System.out.println("不存在该元素");
// }else{
// System.out.println(arr[rep] + " 的下标为" + rep);
// }
// }
// public static int find(int[] arr, int x){
//
// for (int i = 0; i < arr.length; i++) {
//
// if(arr[i] == x)
// return i;
// }
// return -1;
// }
//}
//6 查找数组中指定元素(二分查找) 用递归方法 和 非递归方法写
/**
* 针对有序数组, 可以使用更高效的二分查找
* 有序分为 "升序" 和 "降序"
* 如 1 2 3 4 , 依次递增即为升序.
* 如 4 3 2 1 , 依次递减即为降序.
* 以升序数组为例, 二分查找的思路是先取中间位置的元素,
* 看要找的值比中间元素大还是小. 如果小, 就去左边找;
* 否则就去右边找.
*/
//非递归方法写
//public class Test_4_10_ZY {
// public static int conut = 0;
// public static void main(String[] args) {
//
// int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
// int num = 10;
// int rep = toFind(arr, num);
// System.out.println(conut);
// if(rep == -1){
// System.out.println("不存在该元素");
// }else{
// System.out.println(num + " 的下标为 " + rep);
// }
// }
// public static int toFind(int[] arr, int rep){
//
// int left = 0;
// int right = arr.length - 1;
// int middle = (left + right) / 2;
// while(left <= right){
// conut++;
// if(rep < arr[middle]){
// right = middle - 1;
// }else if(rep > arr[middle]){
// left = middle + 1;
// }else{
// return middle;
// }
// middle = (left + right) / 2;
// }
// return -1;
// }
//}
//用递归方法
//public class Test_4_10_ZY {
// public static int conut = 0;
// public static void main(String[] args) {
//
// int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
// int num = 10;
// //用递归方法需要多输入两个参数:左边的下标 和 右边的下标(范围)
// int rep = toFind(arr, num, 0, arr.length - 1);
// System.out.println(conut);
// if(rep == -1){
// System.out.println("不存在该元素");
// }else{
// System.out.println(num + " 的下标为 " + rep);
// }
// }
// public static int toFind(int[] arr, int rep, int left, int right){
//
// conut++;
// int middle = (left + right) / 2;
//
// if(left <= right){
// //必须是 <= 不然边界值找不到
//
// if(arr[middle] == rep){
// return middle;
// }else if(rep < arr[middle]){
//
// return toFind(arr, rep, left, middle - 1);
// }else if(rep > arr[middle]){
//
// return toFind(arr, rep, middle + 1, right);
// }
// }
//
// return -1;
// }
//}
//7 检查数组的有序性
/**
* 给定一个整型数组, 判断是否该数组是有序的(升序)(降序)
*/
//public class Test_4_10_ZY {
// public static int conut = 0;
// public static void main(String[] args) {
//
// int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
// int[] arr1 = new int[]{9,8,7,6,5};
// int[] arr2 = new int[]{9,8,4,6,5};
// System.out.println("是否是有序:" + Orderly(arr));
// System.out.println("是否是有序:" + Orderly(arr1));
// System.out.println("是否是有序:" + Orderly(arr2));
//
//
// }
// //判断是否升序
// public static boolean Orderly(int[] arr){
//
// if(arr.length <= 1)
// return false;
// if(arr[0] < arr[1]) {
// //判断是否升序
// for (int i = 0; i < arr.length - 1; i++) {
// if (arr[i] > arr[i + 1])
// return false;
// }
// }else if(arr[0] > arr[1]){
// //判断是否降序
// for (int i = 0; i < arr.length - 1; i++) {
// if(arr[i] < arr[i + 1])
// return false;
// }
// }else{
// return false;
// }
//
// return true;
// }
//
//}
//8 数组排序(冒泡排序)
/**
* 功能:给定一个数组, 让数组升序 (降序) 排序
* 算法思路:
* 每次尝试找到当前待排序区间中最小(或最大)的元素, 放到数组最前面(或最后面)
*/
//public class Test_4_10_ZY {
// public static void main(String[] args) {
//
// int[] arr = new int[]{5,3,4,6,7,1,0,8,2};
// sort(arr);
// for (int x :
// arr) {
// System.out.print(x + " ");
// }
// }
// public static void sort(int[] arr){
//
// int input = 0;
// for (int i = 0; i <arr.length; i++) {
//
// input = i;
// for (int j = i; j < arr.length; j++) {
//
// if(arr[input] > arr[j])
// input = j;
// }
// int tmp = arr[i];
// arr[i] = arr[input];
// arr[input] = tmp;
// }
// }
//}
//9 数组逆序
/**
* 给定一个数组, 将里面的元素逆序排列.
* 思路:
* 设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素.
* 然后让前一个下标自增, 后一个下标自减, 循环继续即可.
*/
//import java.util.Arrays;
//public class Test_4_10_ZY {
// public static void main(String[] args) {
//
// int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
// System.out.println("---逆序之前---");
// System.out.println(Arrays.toString(arr));
// Reverse(arr);
// System.out.println("---逆序之后---");
// System.out.println(Arrays.toString(arr));
//
// }
// public static void Reverse(int[] arr){
//
// int left = 0;
// int right = arr.length - 1;
// while(left < right){
//
// int tmp = arr[left];
// arr[left] = arr[right];
// arr[right] = tmp;
// left++;
// right--;
// }
// }
//}
//10 数组数字排列
/**
* 要求:给定一个整型数组,
* 将所有的偶数放在前半部分,
* 将所有的奇数放在数组后半部分
* 方法1:用冒泡法查找,把遇到的偶数排到最前面,以此类推。
* 方法2:设定两个下标分别指向第一个元素和最后一个元素.
* 用前一个下标从左往右找到第一个奇数, 用后一个下标从右往左找到第一个偶数, 然后交换两个位置的元素.
*/
//方法1: 效率慢
//public class Test_4_10_ZY {
// public static void main(String[] args) {
//
// int[] arr = new int[]{5,3,4,6,7,1,0,8,2};
// sort(arr);
// for (int x :
// arr) {
// System.out.print(x + " ");
// }
// }
// public static void sort(int[] arr){
//
// int input = 0;
// for (int i = 0; i <arr.length; i++) {
//
// input = i;
// for (int j = i; j < arr.length; j++) {
//
// if(arr[j] % 2 == 0) {
// input = j;
// break;
// }
// }
// int tmp = arr[i];
// arr[i] = arr[input];
// arr[input] = tmp;
// }
// }
//}
//方法2 : 效率就快很多
//public class Test_4_10_ZY {
// public static void main(String[] args) {
//
// int[] arr = new int[]{5,3,4,6,7,1,0,8,2};
// sort(arr);
// for (int x :
// arr) {
// System.out.print(x + " ");
// }
// }
// public static void sort(int[] arr){
//
// int left = 0;
// int right = arr.length - 1;
//
// while(left < right){
//
// //找到左边的奇数
// while(arr[left] % 2 == 0 && left < right){
// left++;
// }//注释:条件必须是可执行条件,而不是终止条件
// //找到右边的偶数
// while(arr[right] % 2 != 0 && right > left){
// right--;
// }
// int tmp = arr[left];
// arr[left] = arr[right];
// arr[right] = tmp;
// }
// }
//}
5. 二维数组(了解就行)
二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组.相当于多个一维数组的拼接。
基本语法
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
代码示例:
int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr[row].length; col++) {
System.out.printf("%d\t", arr[row][col]);
}
System.out.println("");
}
// 执行结果
1 2 3 4
5 6 7 8
9 10 11 12
同理, 还存在 "三维数组", "四维数组" 等更复杂的数组, 只不过出现频率都很低.
版权归原作者 逆袭者—MA 所有, 如有侵权,请联系我们删除。