黑马程序员--数组
------
Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
数 组
一、定义
数组:同一个类型数据的集合,就是一个容器。优点:从0自动编号,方便操作。
二、格式
(一)一维数组
格式1:元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
例:int[] arr = new int[4]; 或写成 int arr[] = new int[4];
格式2:元素类型[] 数组名 = new 元素类型[]{元素1,元素2,...};(数据明确时使用)
例:int[] arr = new int[]{3,1,6};
格式3:元素类型[] 数组名 = {元素1,元素2,...};(简写的静态初始化格式)
例:int[] arr = {3,1,6};
一维数组内存图:
(二)二维数组
格式1:int[][] arr = new int[3][2];
上述格式表示:二维数组中有3个一维数组,每个一维数组包含2个元素;
格式2:int[][] arr = new int[3][];
上述格式表示:每个一维数组的默认初始化值为null。
格式3:int[][] arr = {{3,8,1},{1,2},{3},...};
上述格式表示:每一个一维数组中具体元素都已经初始化。
注:一种特殊定义写法:int[]x,y[];x是一维数组;y是二维数组。
二维数组内存图:
1、数据类型包括基本类型和引用类型。数组就是一种引用类型
2、内存结构:java中有5个区域存储数据:栈、堆、方法区、本地方法区、寄存器;
栈内存:存储局部变量,数据用完,自动释放。
堆内存: a 数组和对象,通过new建立的实例都在其中;
b 实体中的变量都有默认初始化值;
c 每个实体都有内存地址值;
d 实体不再被使用后,启动垃圾回收机制。
三、数组常见问题
1、ArrayIndexOutOfBoundsException:数组角标越界异常,访问到数组中不存在的角标
class ArrayDemo1
{
public static void main(String[] args)
{
int[] arr = new int[2];
System.out.println(arr[2]);
}
}
运行
结果:
2、NullPointerException:空指针异常
class ArrayDemo2
{
public static void main(String[] args)
{
int[] arr = null;
System.out.println(arr[0]);
}
}
运行
结果:
四、数组常见操作
1、数组排序:常见排序有两种:选择排序、冒泡排序。
选择排序:头角标值和所有值进行比较,内循环结束一次,最值出现在头角标位置上。
冒泡排序:相邻值比较,最值出现在末角标。
java在开发中常使用已定义好的一种排序方法:Arrays.sort(arr);
下面是数组常用代码:
/*
选择排序:
*/
public class ArraySelect1 {
public static void main(String[] args)
{
int[] arr = {1,12,45,17,45,78,72};
//输出原数组
printArray(arr);
//进行选择排序
selectSort(arr);
//输出排序后数组
printArray(arr);
}
/*
* 思路:
* 1,先用0角标元素一次和其他元素比较,在0角标获取最小值;
* 2,再拿1角标元素和其他元素比较,以此类推。
*/
public static void selectSort(int[] arr)
{
//外循环遍历数组
for(int x =0;x<arr.length-1;x++)
{
//内循环比较大小
for(int y =x+1;y<arr.length;y++)
{
//比较大小,进行换值
if(arr[x]>arr[y])
{
swap(arr,x,y);
}
}
}
}
//定义换值方法,arr也是未知变量
public static void swap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
//设置打印格式
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0;x<arr.length;x++)
{
if(x!=arr.length-1)
System.out.print(arr[x]+",");
else
System.out.println(arr[x]+"]");
}
}
}
输出代码:
/*
冒泡排序
*/
public class ArraySelect2 {
public static void main(String[] args)
{
int[] arr = {1,12,45,17,45,78,72};
//输出原数组
printArray(arr);
//进行选择排序
bubbleSort(arr);
//输出排序后数组
printArray(arr);
}
/*
* 思路:比较相邻项 最值在尾部
*/
public static void bubbleSort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)
{
for(int y =0;y<arr.length-x-1;y++)//-x:让每一次比较的元素减少;-1:避免角标越界
{
if(arr[y]>arr[y+1])
{
swap(arr,y,y+1);
}
}
}
}
//定义换值方法,arr也是未知变量
public static void swap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
//设置打印格式
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0;x<arr.length;x++)
{
if(x!=arr.length-1)
System.out.print(arr[x]+",");
else
System.out.println(arr[x]+"]");
}
}
}
输出结果:
/*
* 需求:将一个已知元素插入到一个有序数组中,要求不改变数组顺序,打印元素应该插入数组位置的角标。
* 思路:1、可以利用折半查找的方式,先定义两个变量,一个初始化0角标,作为最小值,一个初始化为最后一个角标,
* 作为最大值。再定义一个变量,存储最小值与最大值的一半(中间值),然后将目标元素与中间值元素进行比较。
* 2、如果中间值大,最大值变为中间值-1,继续用中间值和目标元素比较;如此反复。
* 3、如果目标元素大,最小值变为中间值+1,继续用中间值和目标元素比较;如此反复。
*/
public class HalfSearch {
public static void main(String[] args)
{
int[] arr = {3,4,6,7,9,14,54};
//打印原数组
printArray(arr);
//插入20
int index = 20;
//用方式一输出插入角标值
System.out.println("方式一获取的插入角标值为"+halfSearch_1(arr,index));
index = 4;
System.out.println("方式二获取的插入角标值为。。。。。"+halfSearch_2(arr,index));
}
//折半查找:可提高效率,但必须在有序数组中使用。
public static int halfSearch_1(int[] arr,int key)
{
int min,max, mid;
min = 0;
max = arr.length-1;
mid = (min+max)/2;
while(arr[mid]!=key)
{
if(key>arr[mid])
min = mid +1;
else if(key<arr[mid])
max = mid-1;
if(min>max)
return min;
mid = (max+min)/2;
}
return mid;
}
//折半的第二种方式
public static int halfSearch_2(int[] arr,int key)
{
int min=0,max=arr.length-1,mid;
while(min<=max)
{
mid=max+min>>1;
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
else
return mid;
}
return -1;
}
//设置打印格式
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0;x<arr.length;x++)
{
if(x!=arr.length-1)
System.out.print(arr[x]+",");
else
System.out.println(arr[x]+"]");
}
}
}
输出结果:
/*
* 需求:利用查表法将十进制转换为二进制、八进制、十六进制。
* 思路:1、进制在进行与运算后,会获取相对应的值。
* 2、数组是同一种类型数据的集合,元素和角标具有对应关系;
* 3、将进制封装进数组中。
*/
public class TranstionDemo {
public static void main(String[] args)
{
toBin(0);
show();
toOct(9);
show();
toHex(45);
}
//十进制转二进制
public static void toBin(int num)
{
trans(num,1,1);
}
//十进制转八进制
public static void toOct(int num)
{
trans(num,7,3);
}
//十进制转十六进制
public static void toHex(int num)
{
trans(num,15,4);
}
public static void trans(int num,int base,int offset)
{
//因为所有进制的0值都是0,故单独定义
if(num==0)
{
System.out.print(0);
return;
}
//定义数据库表
char[] chs = {'0','1','2','3',
'4','5','6','7',
'8','9','A','B',
'C','D','E','F'};
//定义临时容器。因为一个char有32个二进制位,故依最多位值设置数组。
char[] arr = new char[32];
//指针代表存入值的位,这样存可使值倒着输出
int pos = arr.length;
//只运算有效位,提高运算效率。
while(num!=0)
{
int temp = num & base;
//--pos是存入角标的移位动作,防止覆盖
arr[--pos] = chs[temp];
//右移位数
num=num>>>offset;
}
//从pos位开始遍历,可以只输出有效位
for(int x=pos;x<arr.length;x++)
{
System.out.print(arr[x]);
}
}
//定义输出函数
public static void show()
{
System.out.println();
}
}
输出结果: