目录
为什么需要数组?
1.变量在内存中开辟一块空间,一维数组在内存中开辟很多块连续的空间;
2.是一种容器,但只能够存储相同类型的一组数据。可以是基本数据类型,也可以是引用数据类型。
使用数组的步骤?
1.声明创建数组;2.数组初始化;3.数组存储;4.遍历数组
一、一维数组
1.声明
- int [ ] a; //int 表示整数类型,[ ] 表示数组类型,int [ ] 表示整型数组类型
- int [ ] a,b,c; //声明a,b,c三个整型数组
- int a[ ],b,c; //声明整型数组a,和两个整型变量b、c
2.初始化
静态初始化:手动指定初始值,系统自动指定数组长度并分配空间。
- int [ ] a = {11, 22, 33, 44}; //静态初始化,只能用一行表示
- a = {11, 22, 33, 44}; //这种写法,编译器报错
- int [ ] a = new int[ ] {11, 22, 33, 44}; //这种就可以拆成两行写
- a = new int[ ] {11, 22, 33, 44};
动态初始化:手动指定数组长度,系统自动给每个元素开辟空间并赋初始值。
- int [ ] a;
- a = new int[4]; //动态初始为各类型的默认值
3.遍历(普通循环或增强for循环)
普通循环或增强for循环的区别:
- 增强for只能顺序遍历,从第一个到最后一个元素
- 增强for只能遍历所有元素,不能遍历部分元素
- 增强for不能改变元素的值
4.复制
方法一:for循环
方法二:使用System.arraycopy( )
int [ ] a = {5, 6, 2, 7, 9};
int [ ] a1 = new int[a.length];
a1 = System.arrayCopy(a, 0, a1, 0, a.length); //参数1:原数组,参数2:原数组起始位置,参数3:目标数组,参数4:目标数组起始位置,参数5:复制长度。
方法三:克隆
int [ ] a = {5, 6, 2, 7, 9};
int [ ] a1 = a.clone( );
5.常用算法
求最大/小值算法
原理:定义变量max或min值保存最大/小值的索引,然后遍历数组更新max或min
实现:(核心代码)
int max = 0;
for(int i = 0; i<a.length; i++) if(a[max] < a[i]) max = i;
排序算法(冒泡、选择、插入)
原理:
- 冒泡排序:将数组中相邻的两个元素进行比较并将最小的元素交换到前面。
- 选择排序:某一位置和后面的所有元素比较
- 插入排序:某个位置和前面的元素一次比较,若小于前面的元素则交换位置,大于则停止比较
实现:
//冒泡排序
for(int i=0; i<a.length; i++){
for(int j=1; j<a.length - i; j++){
if(less(a[j],a[j-1])) exch(a, j, j-1)
}
}
//选择排序
int min = 0;
for(int i=0; i<a.length-1; i++){
for(int j=i; j<a.length; j++){
if(less(a[j],a[min])) min = j;
}
exch(a, i, min);
}
//插入排序
for(int i=1; i<a.length; i++){
for(int j=i; j>0; j--){
if(less(a[j],a[j-1])) exch(a, j, j-1)
else break;
}
}
//比较两个整数,a > b,则返回true;a <= b,则返回false
private static boolean less(int a, int b){
return a < b ? true : false;
}
//交换数组中的两个元素
private static void exch(int[] a, int i, int j){
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
}
二分查找算法
原理:定义3个变量lo,hi,mid,分别存储起始索引,终点索引,以及中间索引,其中,mid = (lo + hi)/ 2。然后比较中间索引所对应的元素值是否与查找值一致,若是,则知道返回mid;若不是,则判断谁大谁小,然后改变相应的起始值或终点至,接着递归或循环次过程。
实现:(循环和递归两种方式)
public class BinarySearch {
/**
* 递归实现 二分查找
* @param key 查找值
* @param a 有序数组
* @return 返回-1,否则返回索引值
*/
public static int binarySearchRecursion(int key, int[] a){
int lo = 1;
int hi = a.length - 1;
return recursion(a, lo, hi, key);
}
/**
* 递归调用
* @param a 数组
* @param lo 起始值
* @param hi 终止值
* @param key 查找值
* @return
*/
public static int recursion(int[] a, int lo, int hi, int key){
if (lo > hi) {
return -1;
}
int mid = (lo + hi) / 2;
if (a[mid] == key) {
return mid;
}else if (a[mid] < key) {
lo = mid + 1;
}else {
hi = mid -1;
}
return recursion(a,lo,hi,key);
}
/**
* 二分查找
* @param key 查找值
* @param a 有序数组
* @return 若未找到,则返回-1;若找到,则返回对应的数组索引
*/
public static int binarySearch(int key, int[] a){
int lo = 0;
int hi = a.length - 1;
while(lo <= hi){
int mid = (lo + hi) / 2;
if (key > a[mid]) {
lo = mid + 1;
}else if (key < a[mid]) {
hi = mid - 1;
}else {
return mid;
}
}
return -1;
}
/**
* 插入排序
* @param a 整型数组
*/
public static void insertSort(int[] a){
for (int i = 1; i < a.length; i++) {
for (int j = i; j > 0; j--) {
if (compare(a[j-1] , a[j])) {
exch(a, j-1, j);
}else {
break;
}
}
}
}
/**
* 比较两个整数的大小
* @param i 整数
* @param j 整数
* @return 若i > j,则返回true;否则,返回false。
*/
public static boolean compare(int i, int j) {
return i > j ? true : false;
}
/**
* 交换数组中的两个元素
* @param a 整型数组
* @param i 数组索引
* @param j 数组索引
*/
public static void exch(int[] a, int i, int j) {
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
}
}
二、二维数组:数组的数组
1.声明
int [ ][ ] a;
2.初始化:静态初始化和动态初始化
静态初始化:
int [ ][ ] a = {{1,2},{3,4},{5,6}};
int [ ][ ] a1;
a1 = new int [ ][ ]{{1,2},{3,4},{5,6}};
动态初始化:
int [ ][ ] a = new int[3][2];
a = new int[3][2];
3.调用
System.out.println(a[2][1]);
4.遍历(双重循环)
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
三、不规则数组:低维的数目不同
int [ ][ ] a = new int[3][ ]; //声明一个不规则数组
System.out.println(a[1]); //输出:null,低纬度的一维数组未分配空间
a[0] = new int[1]; //初始化低纬度的一维数组
a[1] = new int[2];
a[2] = new int[3];
四、多维数组:本质上也是一维数组
五、补充知识
1.Eclipse 报错都是编译阶段的问题,运行阶段的问题只有在运行时才能发现。
2.如果在循环外面声明变量,但是却在循环内初始化该变量,再到循环后使用该变量,编译器会报错。因为for循环和while循环是先判断条件再执行,编译器会考虑到循环里面的代码可能一次也不会执行,所以提示变量未初始化。
3.小数的字面量默认是double类型,就是实在float范围内,但不能自动转换成float类型。这和整型字面量不同。
4.栈(Stack)
作为构思算法的工具,不是完全的数据存储工具,是插入和删除操作被限制在一端的线性表。特点:可以存储基本数据类型和引用数据类型;占用空间小;频繁创建和销毁的一种数据结构:后进先出
ps:方法压栈的时候,会为其分配栈帧
5.堆(heap):用于存储对象,占用存储空间较大,不会频繁创建和销毁。