-------android培训、java培训、期待与您交流! ----------
导读:数组的内存结构,数组表示,排序,查找,进制转换,二维数组
1、概述_内存结构
- 定义:同一种类型数据的集合,其实数组就是一个容器。(数组是存储数据的一种方式)
- 好处:自动给进来的数据进行编号,编号从0开始。方便操作。
- 格式:
(1) int[] arr = new int[3];
(2) int[] arr = new int{3 , 5 , 6 , 7};
(3) int[] arr = {3 , 5 , 6 , 7}
1> arr不是int类型的,而是数组类型的。数的类型分为基本数据类型和引用类型。数组是三种引用类型中的一种。
2> 内存中开辟栈空间,堆空间。栈:数据使用完毕会自动释放。堆:不是。
3>凡是局部变量都是在栈中,局部变量:定义在方法中的变量,定义在方法的参数上的变量,定义在for循环上的变量都是局部的。
4> new出来的东西,为实体,都不在栈里面在堆里面。堆里面存放的都是实体,实体包括数组和对象。
- arr在栈中存放。new int[3]; 在堆中开辟出来三个连续的小格子(int x = 3; 它是在栈中,注意区别),每一个格子都有一个编号。每一个编号对应一个,实体的存放位置(内存地址),数组在堆中存放的时候总有一个起始的位置,这个地址就做为数组的首地址值。将这个地址赋给栈中的arr,这样arr就指向了数组,或者称arr引用了这个数组。(说引用是因为数组没有真正的存放到数组中去只是存了一个地址。)
- 堆内存中的实体是用于封装数据的,而每一个堆内存中的数据都有一个默认的初始化值。要根据数组中数据的类型而定。boolean,默认值为0;
- 在堆内存中没有任何内容能引用它的话,java JVM就视它为垃圾,不定时的启动一个垃圾回收机制,将垃圾清除(不是立即清除的)。
- 堆内存的三个特点:(1)内存地址值(2)默认初始化值(3)垃圾回收机制
- 栈自动释放,堆垃圾回收。
- 只有引用数据类型才能用特殊的常量null. int x[0] = null;表示x不再倾向数组而是表示值为空
- 引用数据类型:可以两个引用在同时操作同一个数组。
- java承载自c++,使其更易学易用。java在内存优化这一块做的比c++要好。c++由程序员手动的调用一个功能将内存中的数据清除掉。如果程序员忘记做了,程序运行时间越长,程序越慢,甚至死机。
2、静态初始化_常量问题
通过大括号的形式标识出了元素的内容。如下所示:
//在[]中不要写长度。因为在后面你的个数和内容已经指定如果你指定一个长度,可能出错。
//数据明确的情况下可以用下面这种格式.
int[] arr = {3 , 5 , 6 , 7} 可以看作是上面的一个简化的形式。
//如果数据不明确可以这样写
int [] arr = new int [5];
arr[0] = 90;
arr[1] = 80;
System.out.println("int[3]");
编译的时候不报错因为编译的时候只检查语法错误。new的实体,是在运行的时候才建立的。
ArrayIndexOutOfBoundsException : 操作数组时,访问到了数组中不存在的角标。
NullPointerException : 空指针异常:当引用没有任何指向值为null的情况,该引用还在用于操作实体。
- 数组的操作:
(1)获取数组中的元素。通常会用去遍历。(见数组通常用for循环,用完之后,会自动消失)
不能用:System.out.println(arr); 会得不到想要的结果。 示例:[I@de6ced意思输出的是一个数组,整型的,@后面是引用的地址,用十六进行表示。
(2)获取数组的最值。
方法一:借助变量int max;在赋初值的时候,可以赋给数组中的任何一个值。如:max = arr[0];
方法二:可不可以将临时变量初始化为0呢?
可以。这种方式,其实是在初始化为数组的角标。如:int max = 0; arr[max]
3、选择排序
内循环结束一次,最值出现头角标位置上。
4、冒泡排序
- 相邻的两个元素进行比较,如果符合条件换位。
- 内循环:for(int y = 0; y<arr.length-x-1; y++)-x的目的是:让每一次比较的次数减少。-1的目的是避免角标越界。
- 排序中最快的排序是希尔排序:三层循环加上位运算。
- 如果数组中的元素比较多,那么么就要考虑代码的效率问题和性能问题。每一次符合条件,都要出现换位,在堆内存中换位比较消耗资源。
- 能不能把要换位的先不换位,在先在栈内存中存起来,所有的都比较完了,再统一的把位置换过来。即把在堆内存中频繁的换位置,转移到栈内存中。如冒泡排序,一圈只换一次位置。
- 真实开发:要求快速,简单。
import java.util.*;
Arrays.sort(arr);
一方面,自己写的代码不够优化,不够好。另一方面,自己手写的方法会出错。
5、位置转换功能抽取
无论是什么排序,都需要位置的置换。
//有三个不确定的量。数组arr, a, b
public static void swap(int[] arr, int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
6、数组的查找:
- 第一种方法:找不到 return -1; 数组是从0开始的,用一个负数表示,表示角标不存在,即数不存在,没有找到想要找的数。
- 第二种方法:折半查找。缩小范围查找,可以提高效率,但必须有一个条件,数组必须有序。
两种写法:
第一种:
public static int halfSearch(int[] arr,int key)
{
int min,max,mid;
min = 0;
max = arr.length-1;
mid = (max+min)/2;
while(arr[mid]!=key) //mid值和key值进行判断
{
if(key>arr[mid])
min = mid + 1;
else if(key<arr[mid])
max = mid - 1;
if(min>max)
return -1; //当min和max相等的时候,会再进行一次折半
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;//找到mid返回
}
return -1; //没有找到.
}
- 练习:有一个有序的数组,想要将一个元素插入到该数组中,还要保证该数组是有序的。如何获取该元素在数组中的位置。
答:将上面第二种写法的return -1;改为return min; 如果数组中原来有要插入的数,如{2, 3, 5, 8, 13, 16},将会将8插入后,其余的后移,变为:{2, 3, 5, 8, 8, 13, 16}. 如果没有找到8,返回最小角标的值,得到原来的插入位置.
7、十进制转换为二进制:
第一种方式:
System.out.println(num%2);num = num / 2;
第二种方式:
public static void toBin (int num)
{
8、十进制转化为十六进制(十进制转化为二进制、十进制转化为八进制类似)StringBuffer sb = new StringBuffer(); //这是一个存储数据的容器while(num > 0){sb.append(num % 2); //对所有的余数进行添加num /= 2;}System.out.println(sb.reverse()); //对所有添加的数进行反转}
- 第一种方法:(char)(temp-10+'a')
- 第二种方法:
查表法:将所有的元素临时存储起来。建立对应关系。每一次&15后的值作为索引去查建立好的表。就可以找对应的元素。这样比 -10+'a'简单的多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 A B C D E F
public static void toHex(int num) //可以打印正数,也可以打印负数,因为都是以二进制的形式存在。
{
//定义一个char类型的数组
char[] chs = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//除了可以用StringBuffer外,还可以定义一个普通临时容器,即数组。
char[] arr = new char[8]; //字符类型的默认初始化值为:'\u0000',表示空位。int pos = arr.length; //可定义一个指针,即数组的角标定义输出。
while(num!=0)
{
int temp = num & 15;
arr[--pos] = chs[temp];
//如果倒着存的话,数组中存的已经是正确的数据,不用倒着输出了。num = num >>> 4;
}
//存储数据的arr数组遍历。
for(int x=pos;x<arr.length; x++)
{
System.out.print(arr[x]+",");
}
}
10、二维数组
第一种方式:
int[][] arr = new int[3][]; //默认初始化为null。二维中的每一个一维数组都为引用类型的。第二种方式:
arr[0] = new arr[3]; //手动初始化。
arr[1] = new arr[1];
arr[2] = new arr[2];
上面是一个不规则数组
int[][] arr = {{2, 5, 1, 7},{2, 3, 5, 8},{6, 1, 8, 2}};
11、数组的定义
int[] x; int y[]; //一维数组的定义
int[][] x; int y[][]; int[] y[]; //二维数组定义
int[] x,y[];//x是一维的数组,y是二维的数组;(开发的时候不用。sun考试的时候可以会用到)