黑马程序员_Java基础_数组_04

                                          -------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) 

{

StringBuffer sb = new StringBuffer();   //这是一个存储数据的容器
while(num > 0)
{
sb.append(num % 2);    //对所有的余数进行添加
num /= 2;
}
System.out.println(sb.reverse());  //对所有添加的数进行反转

}


8、十进制转化为十六进制(十进制转化为二进制、十进制转化为八进制类似)
  • 第一种方法:(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考试的时候可以会用到)


                          ------- android培训java培训、期待与您交流! ----------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值