---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ---------------------
2013-02-20 03:16 45人阅读 评论(0) 收藏 举报5.0数组
5.0.1数组的定义
a) 概念
同一种类型数据的集合。其实数组就是一个容器。
b) 数组的好处
可以自动给数组中的元素从0开始编号,方便操作这些元素
c) 格式1
元素类型[] 数组名 = new 元素类型 [元素个数或数组长度];
元素类型 数组名[] = new 元素类型 [元素个数或数组长度];
(以上两种格式都可以,以第一种格式居多)
示例:int[] arr= new int[5];
d) 格式2(静态初始化方式)
元素类型[] 数组名 =new 元素类型[]{元素,元素,……};
int[] arr = new int[]{3,5,1,7};//此时数组不写长度
int[] arr={3,5,1,7};//也可简写为此
5.0.2数组的内存结构图示
2. 数组的内存分配及特点
java程序运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据的方式和内存管理方式。
a) 栈内存
i. 用于存储局部变量,当数据使用完,所占空间会自动释放
b) 堆内存
i. 数组和对象,通过new建立的实体都存放在堆内存中
ii. 每一个实体都有内存地址值
iii. 实体中的变量都有默认初始化值(以数据类型确定)
iv. 实体不再被使用,会在不确定的时间内被垃圾回收器回收
5.0.4数组操作常见问题
c) 数组脚标越界异常
i. 英文为:ArrayIndexOutOfBoundsException
ii. 编译通过(只检查语法错误),new在运行后才会建立,并在堆内存中建立空间
int[] arr = new int[2];
System.out.println(arr[3]);
iii. 访问到了数组中的不存在的脚标时发生。
d) 空指针异常
i. 英文为:NullPointerException
ii. 编译通过(只检查语法错误),运行时没有指向
int[] arr =null;
System.out.println(arr[0]);
iii. arr引用没有指向实体,却在操作实体中的元素时。
e) 打印出数组地址
i. int[] arr ={2,4,6,7};
ii. System.out.println(arr);
iii. 运行结果:[I@6bbc4459:分解说明:[(数组类型)I(int型)@(地址)6bbc4459(通过哈希算法算出的内存中的地址值是一个哈希值,是一个十六进制)。
iv. [I@6bbc4459:打印了一个数组实体的引用
5.0.5数组常见操作
f) 获取最值(最大值、最小值)(适合于数值型数组)
i. 在为max和min赋初始化值的时候,可以有两种方式:
1. int max = arr[0];赋值为数组的第一个元素;
2. int max = 0;赋值为数组的脚标值,代码如下:if(arr[x]>arr[max])
max=x;System.out.println(arr[max]);
g) 排序(选择排序、冒泡排序)
i. 选择排序
1. 选择固定的一个位置和拿这个位置上的值,不断的和别的位置的值比较,若换完位以后还拿这个位置上的值,和其他位置的值进行比较。
2. 选择排序特点:内循环结束,最值出现在开始脚标位置
3. 关键代码如下:
//外循环排序
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;
}
ii. 冒泡排序
1. 相邻的两个元素进行比较,如果符合条件换位。
2. 关键代码:
//外循环控制循环的轮数
for (int x=0;x<arr.length-1 ;x++ )
{//内层循环控制相邻的比较
//-x:让每一次比较的元素减少,
//-1:避免角标越界。
for (int y =0;y<arr.length-x-1 ;y++ )
{
if(arr[y]>arr[y+1])
{
int temp =arr[y];
arr[y] = arr[y+1];
arr[y+1] =temp;
}
}
iii. 最快的排序是:希尔排序,三层循环加上位运算
iv. java开发中要使用的代码:Arrays.sort(arr);此句代码需要引入:import java.util.*;
v. 发现无论什么排序。都需要对满足条件的元素进行位置置换。所以可以把这部分相同的代码提取出来,单独封装成一个函数。
抽取交换的共性代码为一个函数的代码如下:
public static voidswap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
h) 折半查找(二分查找)
i. 当在数组中没有查找到结果时,一个惯例就是返回“-1”,因为java数组的脚标是不会出现负数的。一般查找的都是数组中的第一次出现该元素的位置。
ii. 提高了效率,但是必须要保证该数组是有序的数组
java提供好的一个进行折半查找的功能。开发时使用(演示)
import java.util.*;
int x =Arrays.binarySearch(arr,90);
System.out.println("x="+x);
遍历数组:当要查找的元素与数组元素相同时(演示)
for(int x=0;x<arr.length; x++)
{
if(arr[x]==key)
return x;
}
return -1;
折半查找:折半后的min和max比较判断循环
int min = 0,max =arr.length-1,mid;//脚标值
while(min<=max) //满足就折半查找
{
mid = (max+min)>>1;
if(key>arr[mid])//如果大于折半脚标
min = mid + 1;//最小脚标为折半脚标+1
else if(key<arr[mid])//如果小于折半脚标
max = mid - 1;//最大脚标为折半脚标-1
else
return mid;//等于折半脚标就是找到元素
}
return -1;//找不到元素返回值-1
折半查找:用中间值和key比较来循环,移动min和max比较
int min,max,mid;
min= 0; max = arr.length-1;
mid= (max+min)/2;
while(arr[mid]!=key)//利用中间值和key比较
{
if(key>arr[mid])
min= mid + 1;
elseif(key<arr[mid])
max= mid - 1;
//之后比较min和max的值
if(min>max)//越界,没有找到
return-1;
mid= (max+min)/2;//算出新的中间值继续
}
returnmid;
折半查找延伸:在有序数组中插入目标元素
int min = 0,max = arr.length-1,mid;
while(min<=max)
{
mid= (max+min)>>1;
if(key>arr[mid])
min = mid + 1;
elseif(key<arr[mid])
max= mid - 1;
else
returnmid;
}
returnmin;
i) 获取数组长度:数组长度 = 数组名.length
j) 遍历数组
i. 使用for循环,数组长度
5.0.6数组中的数组
k) 二维数组[][]
i. 格式1:int[][] arr = new int [3][2];
1. 定义了名称为arr的二维数组
2. 二维数组中有3个一维数组(二维数组的长度)
3. 每一个一维数组中由2个元素(二维数组中每一个一维数组的长度)
4. 一维数组的名称分别为arr[0],arr[1],arr[2]
5. 给第一个一维数组1脚标位赋值为78的写法:arr[0][1]=78;
6. 可以通过打印二维数组中的元素,明确二维数组的初始化特点,此格式下:
a) 打印System.out.println(arr);结果为:[[I@6bbc4459:二维数组int类型的哈希值;
b) 打印System.out.println(arr[]);结果为: [I@6bbc4459:一维数组int类型的哈希值;
c) 打印System.out.println(arr[0][0]);结果为:0它是一个二维数组元素;
ii. 格式2:int[][] arr = new int [3][];
1. 二维数组中有3个一维数组
2. 每个一维数组都是默认初始化值null
3. 可以对这个三个一维数组分别进行初始化
arr[0] =new int [3];
arr[1] =new int [1];
arr[2] =new int [2];内存分配图:
在此情况下打印数组长度:
System.out.println(arr.length);//打印是二维数组的长度 3;System.out.println(arr[0].length);//打印二维数组中第一个一维数组长度3
4. 此格式下
a) 打印System.out.println(arr);结果为:[[I@6bbc4459:二维数组int类型的哈希值;
b) 打印System.out.println(arr[0]);结果为:null:为这个数组的默认初始化值,堆内存中开辟空间但是没有初始化值。
c) 打印System.out.println(arr[0][0]);结果为:NullPointerException
iii. 格式3:int[][] arr = {{3,8,2},{2,7},{9,0,1,6}};
1. 定义一个名称为arr的二维数组
2. 二维数组中的有三个一维数组
3. 每一个一维数组中具体元素也都已初始化
4. 第一个一维数组arr[0]={3,8,2}
5. 第二个一维数组arr[1]={2,7}
6. 第三个一维数组arr[2]={9,0,1,6}
7. 第三个一维数组的长度表示方式:arr[2].length;
iv. 练习:获取arr数组中所有元素的和。使用for的嵌套循环即可。
二维数组的应用:所有元素之和,关键代码如下:
int sum = 0;
for(intx=0; x<arr.length;x++)
{
for(inty=0; y<arr[x].length; y++)
{
sum= sum + arr[x][y];
}
v. 注意特殊的写法:
1. 一维数组的写法:
a) int[] x;
b) int x[];
2. 二维数组的写法
a) int[][] y;
b) int y[][];
c) int[] y[];
3. int[] x,y[];x是一维数组,y是二维数组。
5.0.7练习(进制转换)
l) 进制转换
i. 十进制转二进制
关键代码:(红色代码也可以单独实现)
StringBuffer sb = new StringBuffer();
while(num>0)
{
//System.out.println(num%2);
sb.append(num%2);
num = num / 2;
}
System.out.println(sb.reverse());
//输出反转
ii. 十进制转十六进制
1. 关键代码:先&15,判符号,无符号右移
StringBuffer sb = new StringBuffer();
//int型数据4个字节32个二进制位,故8次移位
for(int x=0; x<8; x++)
{
inttemp = num & 15;
if(temp>9)
//System.out.println((char)(temp-10+'A'));
sb.append((char)(temp-10+'A'));
else
//System.out.println(temp);
sb.append(temp);
num = num >>> 4;
}
System.out.println(sb.reverse());
iii. 查表法十进制十六进制
1. 将所有的元素临时存储起来,建立对应关系。
2. 每一次&15之后的值作为索引去查建立的表,就可以找对应的元素,这儿样比“x-10+’a’”方便。
3. 代码步骤:创建查询表,创建临时存储结果表,创建指针,通过循环将结果与指针相关联,右移,遍历打印。
public static void toHex(int num)
{//创建字符数组,以作为十六进制查询表
char[] chs = {'0','1','2','3',
'4','5','6','7',
'8','9','A','B',
'C','D','E','F'};
//定义一个临时容器。存储移位后的十六进制数
char[]arr = new char[8];
//定义一个指针,并指向最后一个元素,(倒着存)
intpos = arr.length;
while(num!=0)//当num有效位右移完之后不循环
{
inttemp = num & 15;
//System.out.println(chs[temp]);
//查询表,并将其存入临时表的最后一个空间中
arr[--pos]= chs[temp];
num= num >>> 4;//无符号右移
}
System.out.println("pos="+pos);//打印指针的值
//存储数据的arr数组遍历。
for(intx=pos;x<arr.length; x++)
{
System.out.print(arr[x]+",");
iv. 查表法十进制二进制
1. 原理同十进制向十六进制转换相同
2. 关键代码如下:
public static void toBin(int num)
{ //定义二进制的表。
char[]chs = {'0','1'};
//定义一个临时存储容器。
char[]arr = new char[32];
//定义一个操作数组的指针
intpos = arr.length;
while(num!=0)
{
inttemp = num & 1;
arr[--pos]= chs[temp];
num= num >>> 1;
}
for(int x=pos; x<arr.length; x++)
{
System.out.print(arr[x]);
v. 查表法向十进制与二进制转换的优化
public static void main(String[] args)
{
toBin(-6);
toHex(-60);
toBa(60);
// System.out.println(Integer.toBinaryString(6));
// System.out.println(Integer.toHexString(6));
}
// 十进制-->二进制
public static void toBin(int num)
{
trans(num,1,1);
}
//十进制-->八进制
public static void toBa(int num)
{
trans(num,7,3);
}
//十进制-->十六进制
public static void toHex(int num)
{
trans(num,15,4);
}
public static void trans(int num,intbase,int offset)
{
if(num==0)//判断特殊情况,如果是0就直接打印
{
System.out.println(0);
return;
}
char[]chs = {'0','1','2','3'
,'4','5','6','7'
,'8','9','A','B'
,'C','D','E','F'};
char[]arr = new char[32];
intpos = arr.length;
while(num!=0)
{
inttemp = num & base;
arr[--pos]= chs[temp];
num= num >>> offset;
}
for(intx=pos; x<arr.length; x++)
{
System.out.print(arr[x]);
}
return;
}
}
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ---------------------