Java数组总结

来源:互联网 发布:华为交换机 允许mac表 编辑:程序博客网 时间:2024/06/05 22:49

数组是Java中一种非常有用的数据结构,今天就来总结一下,以下是这篇博客的大纲:

一.数组的概念和特点

二.数组的种类和应用场景

三.数组的几种创建方式

四.数组相关的几种常用算法

五.数组的底层实现

六.数组与其他数据结构的优缺点比较



一.数组的概念和特点

java数组是同一种类型数据的集合,其实就是一个容器,数组中的元素可以是任意类型(基本类型或引用类型),在声明的时候需要指定长度,在内存中是连续存放的。数组是存在下标缩印的,通过下标可以获取指定位置的元素,从0开始,即下标0对应数组中的第一个元素,可以很方便的对数组中的元素进行查找操作。


二.数组的种类和应用场景

数组从顺序上划分可分为有序数组和无序数组,有序数组即数组中的元素按照某种标准升序或者降序排列好,无序数组即数组内的元素没有任何规律。基于二分法查找的数组就必须要是有序数组。

    从数组元素来说还可以分为一维数组,二维数组和多维数组。其实很好理解,多维数组可以理解为一维数组的嵌套,java是不存在真正的二维数组和多维数组的,拿二维数组来说,其实是一个保存着引用变量的特殊一维数组,这个特殊的一维数组里面的每个元素都是一个引用变量,这每一个引用变量都指向另一个数组。

因为数组是连续存储的,在内存里面是连续的,在存储之前需要申请一块连续的内存空间,并且在变异的时候就确定好了空间的大小,在运行的时候空间的大小是无法随着我们的需要进行增加和减少而改变的。所以,数组适用于这样的应用场景:数据元素不太多;经常做的运算是根据序号访问数据元素;构建的线性表比较稳定,不需要扩容或者减少数组容量大小。


三.数组的几种创建方式

以String数组为例,有以下三种方式,工作中基本用到的都是第一种。

1.String[] a = new String[length];

          a[0]=?;......

2.String[] a = new String[]{?,?...};

3.String[] a = {?,?....};

在内存中的表示如下图所示:


四.数组相关的几种算法和常用方法

1)冒泡排序

1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 
2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 
3. 针对所有的元素重复以上的步骤,除了最后一个。 
4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

public class BubbleSort{    public static int[] bubbleSort(int[] array){        for(int i = 0;i < array.length;i++){                                                        for(int j = 0; j < array.length-i-1;j++){                if(array[j] > array[j+1]){                                            int temp = array[j];                      array[j] = array[j+1];                     array[j+1] = temp;                    }            }            System.out.println("第"+(i+1)+"趟排序");            for(int k = 0;k < array.length;k++){                System.out.print(array[k]+"  ");            }            System.out.println();        }        return array;    }    /**     * @param args     */    public static void main(String[] args){        int[] array = {7,3,9,5,6,8,1};        bubbleSort(array);    }}

2)二分法查找

二分查找又称折半查找,是一种效率较高的查找方法。这种方法查找比较次数少,查找速度快,平均性能好,但是要求待查的表为有序的,插入删除困难,因此适用于不经常变动而查找频繁的有序列表。

算法步骤:首先将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

算法复杂度:假设其数组长度为n,其算法复杂度为o(log(n)),最坏情况下的时间复杂度是O(n)

  /**     * 如果找到对应value则返回对应元素数组下标,否则返回-1     *     */   public static int binarySerarch(int[] array, int value) {      int bottom = 0;      int top = array.length - 1;      while (bottom < top) {          int mid = (bottom + top) / 2;          if (array[mid] == value) {             return mid;           } else if (array[mid] < value) {              bottom = mid + 1;           } else {              top = mid - 1;           }       }      return -1;    }   public static void main(String[] args) {      int[] array = { 1, 3, 5, 7, 11, 21, 33, 54, 72, 91, 93, 99 };      int value = 72;      System.out.println(binarySerarch(array, value));    }


五.数组的底层实现

比如:int[],int告诉计算机这是一个整型数据,[]告诉计算机这是一个连续存储的内存地址空间,简单的说就是一个连续数据的存储空间就是数组,数组只是一个名称


六.数组与其他数据结构的优缺点比较

  数组是线性表顺序存储的一种实现,在内存中是一块连续的存储空间,逐个存放,也就是说倘若数组的第一个元素在地址A,则数组第二个元素就在地址A+1;依此类推。所以,在线性表中访问数据元素是很快的。它的缺点也正因为它是连续的一块内存空间。所以,如果往中间添加或在中间删除一个元素。都要移动其他的元素。如:我在最前面加入一个元素:0.则1,2,3都要往后移一位;或,我将1删除,则2,3都要往前移一位;估算一下运算时间:在第一个元素处添加,要移动所有的元素。花费的时间是添加元素的时间 X 加上移动其他元素的时间:N,在最后面加元素不需要移动任何元素。时间仅为添加元素的时间: X .所以添加元素要的平均时间是 (N + 2X)/2;删除操作和添加操作是一样的;所以,当改变线性表长度的时间,它会在移动元素上花费大量的时间在JAVA中。线性表的最直接应用就是数组Array;但Array在初始化的时间必须规定其元素长度。如:int[] arr = new int[5];必须规定其长度,但内容可以不填。它要知道长度,然后去开辟一块内存空间。一旦数组初始化,它就不能往里面添加,删除元素了。但可以将元素值设为空。(我们常用的ArrayList就是用数组实现的一种顺序表)

链表是线性表链式存储的一种实现,比如单链表,它不强迫数据是在一片连续的内存空间,可以使分散存储的,所以它的每个元素除了包括元素的值外,还要包括一些额外的信息,分为数据域和指针域,数据域用来存储数据,指针域用来存储指向下一个节点的对象的引用。此外还有双链表等。如下图给出单链表和双链表的结构



 数组与链表的优缺点;    
    数组:

    优点:使用方便 ,查询效率 比链表高,内存为一连续的区域 

    缺点:大小固定,不适合动态存储,不方便动态添加
    链表:

     优点:可动态添加删除   大小可变   
     缺点:只能通过顺次指针访问,查询效率低

 补充:

顺序表的优点:查找方便,适合随机查找 
顺序表的缺点:插入、删除操作不方便,因为插入、删除操作会导致大量元素的移动 

链接表的优点:插入、删除操作方便,不会导致元素的移动,因为元素增减,只需要调整指针。 
顺序表的缺点:查找不方便,不适合随机查找