黑马程序员——JAVA 数组

来源:互联网 发布:js同源是什么意思 编辑:程序博客网 时间:2024/06/05 15:30
------- android培训、java培训、期待与您交流! ----------

数组定义方法
           数组是有序数据的集合,数组中的每个元素具有相同的数组名和下标来唯一地确定数组中的元素。
格式:type arrayName[ ];     type[ ] arrayName;
       其中类型(type)可以为Java中任意的数据类型,包括简单类型组合类型,数组名arrayName为一个合法的标识符,[]指明该变量是一个数组类型变量。
数组初始化
   1.动态初始化:数组定义与为数组分配空间和赋值的操作分开进行;
   2.静态初始化:在定义数字的同时就为数组元素分配空间并赋值;
   3.默认初始化:数组是引用类型,它的元素相当于类的成员变量,因此数组分配空间后,每个元素也被
按照成员变量的规则被隐式初始化。
实例:TestD.java(动态)

  1. public class TestD  
  2. {  
  3.      public static void main(String args[]) {  
  4.          int a[] ;  
  5.          a = new int[3] ;  
  6.          a[0] = 0 ;  
  7.          a[1] = 1 ;  
  8.          a[2] = 2 ;  
  9.          Date days[] ;  
  10.          days = new Date[3] ;  
  11.          days[0] = new Date(2008,4,5) ;  
  12.          days[1] = new Date(2008,2,31) ;  
  13.          days[2] = new Date(2008,4,4) ;  
  14.      }  
  15. }  

TestS.java(静态):

  1. public class TestS     
  2. {     
  3.      public static void main(String args[]) {     
  4.          int a[] = {0,1,2} ;     
  5.          Time times [] = {new Time(19,42,42),new Time(1,23,54),new Time(5,3,2)} ;     
  6.      }     
  7. }

数组操作中常见的错误
ArrayIndexOutOfBoundsException:3:操作时,访问到了数组中不存在的角标
NullPointerException:空指针异常;当引用没有任何指向值为null的情况,该引用还在用于操作实体。
[I@36db4bcf 当显示这个是 是把数组中的地址打印出来了@后面为数组地址
      例如:System.out.println(arr);arr是一个数组名,arr本身代表数组首地址,严格说应是一个指针。所以进行如上操作时打印的不是数组而是数组首地址。


数组中的操作方法

获取数据

      获取数组中的元素。通常会用到遍历。所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题。数组正是通过遍历的方式来获取数组中的元素。

例如:定义功能,用于打印数组中的元素。元素间用逗号隔开。

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,当所有的元素都比较完成,那么该变量中存储的就是数组中的最大值了。
步骤:
       1,定义变量。初始化为数组中任意一个元素即可。
       2,通过循环语句对数组进行遍历。
       3,在变量过程中定义判断条件,如果遍历到的元素比变量中的元素大,就赋值给该变量。
需要定义一个功能来完成。以便提高复用性。
       1,明确结果,数组中的最大元素 int。
        2,未知内容:一个数组。int[]
public static int getMax(int[] arr)
{
      int max = arr[0];
      for(int x=1; x<arr.length; x++)
      {
            if(arr[x]>max)
                  max = arr[x];
      }
       return max;
}

获取最小值。原理和活的最大值相同。代码如下:
public static int getMin(int[] arr)
{
       int min = 0;
       for(int x=1; x<arr.length; x++)
       {
             if(arr[x]<arr[min])
             min = x;
       }
       return arr[min];
}

数组排序
    JAVA中在运用数组进行排序功能时,一般有四种方法:快速排序法、冒泡法、选择排序法、插入排序法。
1、利用Arrays带有的排序方法快速排序
   该排序算法是一个经过调优的快速排序法,对指定 int 型数组的指定范围按数字升序进行排序。排序的范围从索引fromIndex(包括)一直到索引toIndex(不包括)。
 public class Study {  
    public static void main(String[] args) {  
        int[] a = { 5, 4, 2, 4, 9, 1 };  
        Arrays.sort(a);  
        for (int i : a) {  
            System.out.println(i);  
        }  
    }  
}   
2、冒泡排序
   冒泡排序:它的时间复杂度为O(n^2),有两个优点:1.“编程复杂度”很低,很容易写出代码;2.具有稳定性,这里的稳定性是指原序列中相同元素的相对顺序仍然保持到排序后的序列,而堆排序、快速排序均不具有稳定性。不过,一路、二路归并排序、不平衡二叉树排序的速度均比冒泡排序快,且具有稳定性,但速度不及堆排序、快速排序。
   基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。
public static void maopao (int[] arr)
{
    for (int x=0;x<arr.length-1 ;x++ )
    {
        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;
             }
         }
    }
}

3、选择排序算法
   选择排序过程中,所需移动记录的次数比较少。最好情况下,即待排序记录初始状态就已经是正序排列了,则不需要移动记录。最坏情况下,即待排序记录初始状态是按逆序排列的,则需要移动记录的次数最多为3(n-1)。简单选择过程中需要进行的比较次数与初始状态下待排序的记录序列的排列情况无关。当i=1时,需进行n-1次比较;当i=2时,需进行n-2次比较;依次类推,共需要进行的比较次数是∑ =(n-1)+(n-2)+…+2+1=n(n-1)/2,即进行比较操作的时间复杂度为O(n2)。这种方法其实是对冒泡排序的深入。
public static void paixu(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])
           {
             int temp=arr[x];
             arr[x]=arr[y];
             arr[y]=temp;
           }
        }
      }
}

4、折半插入排序
   折半插入排序(binary insertion sort)是对插入排序算法的一种改进,由于排序算法过程中,就是不断的依次将元素插入前面已排好序的序列中。由于前半部分为已排好序的数列,这样我们不用按顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度。
在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素小,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),如此直至low<=high不成立,将此位置之后所有元素后移一位,并将新元素插入a[high+1]。
折半插入排序算法是一种稳定的排序算法,比直接插入算法明显减少了关键字之间比较的次数,因此速度比直接插入排序算法快,但记录移动的次数没有变,所以折半插入排序算法的时间复杂度仍然为O(n^2),与直接插入排序算法相同。
    public static int[] halfInsert(int[] R) {  
        for (int i = 1; i < R.length; i++) {// 从第二个元素开始,需要做n-1趟插入排序,第一个元素自成有序区  
            int temp = R[i];// 暂存  
            int low = 0;// 定义从第一个元素开始为有序区  
            int high = i - 1;// 有序区的元素从一个开始逐渐增加  
                                // low和high分别指向有序区中的第一个和最后一个元素  
            while (low <= high) {// 寻找在有序区中插入的位置,最后使high<low,就找到插入的位置  
                                    // 为high+1;也是low的位置  
                int m = (low + high) / 2;// 有序区的中间元素  
                if (temp < R[m]) {// 如果比中间的元素小,则插入位置在低半区  
                    high = m - 1;  
                } else  
                    // 否则,插入位置在高半区  
                    low = m + 1;  
            }  
            for (int j = i; j > low; j--) {// 把从low开始以后或high+1以后的元素向后移动,插入  
                R[j] = R[j - 1];// 移动元素  
            }  
            R[low] = temp;// 插入在合适的位置  
        }  
        return R;  
    }  
}  


0 0