Java数据结构与算法(一)--数组

目录

数组是应用最广泛的数据存储结构。它被植入大部分的编程语音。在Java中数组用来存放一种类型的集合。 

1.数组的介绍                                                                     

①数组的声明

  第一种方式:

int[] arr = new int[10];//数组类型[] 数组名称 = new 数组类型 [数组大小];

  创建数组并声明数组大小  

  第二种方式:

int[] arr = new int[]{1,2,3,4};//数组类型[] 数组名称 = new 数组类型[数组元素1,数组元素2.......];

  创建数组并直接初始化数组里的元素

②访问数组元素及给数组元素赋值

  数组在内存中是连续的数据结构,在运行期间不可变。它有一个下标,从0给数组计数。通过访问下标即可快速的访问和修改数组

        //新建一个长度为4数组
        int[] arr = new int[]{1,2,3,4};
        //访问数组的第一个元素
        int i = arr[0];
        //修改数组的第二个元素
        arr[1] = i;

③数组的遍历

数组具有一个length属性表示数组长度,通过下标和length可以遍历数组

        for (int j = 0; j < arr.length; j++) {
            System.out.println(arr[j]);
        }

2.类封装                                                                          

  使用类来封装数组,使用户不必了解数组的结构而可以直接通过insert/delete/find/display方法来使用数组

/**
 * 实现基本的数据结构功能
 * 1.查找
 * 2.插入
 * 3.删除
 * 4.迭代
 */
public class MyArray {
    //存储数据的数组
    private int[] array;
    //数组内实际元素个数
    private int elems;
    //数据最大容量
    private int length;

    public MyArray(){
        this.elems = 0;
        this.length = 50;
        array = new int[length];
    }

    public MyArray(int length){
        this.elems = 0;
        this.length = length;
        array = new int[length];
    }

    //根据下标查找数据元素
    public int get(int i){
        if(i<0 || i>=elems)System.out.println("数组越界");
        return array[i];
    }

    //在数组末尾插入元素
    public void insert(int i){
        if(elems==length)System.out.println("数组已达到最大容量,需要扩容");
        array[elems] = i;
        elems++;
    }

    //删除指定元素 true删除成功 false删除失败
    public boolean delete(int value){
        int k = find(value);
        if(k==-1){
            return false;
        }else{
            for (int i = k; i <elems-1 ; i++) {
                array[k] = array[k+1];
            }
            elems--;
        }
        return true;
    }

    //查询指定元素,返回元素下标,没有找到返回-1
    public int find(int value){
        for (int i = 0; i < elems; i++) {
            if(array[i]==value)return i;
        }
        return -1;
    }

    //遍历数组
    public void display(){
        for (int i = 0; i <elems ; i++) {
            System.out.println(array[i]);
        }
    }
}

3.扩展(有序数组)                                                           

   前面我们封装了一个无序数组,无序数组在不知道下标的情况下,通过一个一个的遍历比较来查找元素,时间复杂度为O(n),效率不是很高

  我们决定优化下它,首先使数组成为一个有序数组,find方法使用二分查找的方式,不断对半减少查找范围,时间复杂度为O(logn)

  查询过程可以参考下图:

   //当数组有序的时候,使用二分查找,查询指定元素
    public int find(int value){
        int low = 0;
        int high = elems-1;
        int cur;

        while (true){
            cur = low + (high-low)/2;
            if(array[cur]== value){
                return cur;
            }else if(low > high){
                return -1;
            }else if(array[cur]>value){
                high = cur -1;
            }else{
                low = cur +1;
            }
        }
    }

4.数组的局限                                                                 

   上面我们介绍了数组,数组似乎可以完成所有工作,但我们不用它作为所有的数据存储,是因为数组的缺陷。

  (1) 数组在知道下标的时候查询效率很高,但不知道下标查询指定元素的时候效率却很低

  (2)向指定位置修改和删除数据的时候,数组需要移动数组,来保持数组的连续性。移动数组其实就是重新拷贝一个数组,这个过程比较耗时

  (3)创建出的数组大小固定,容量过大会导致浪费,容量过小,数组很容易达到最大容量,导致数组下标越界

  为了解决这种情况,我们需要更加灵活的数据结构。

 

posted @ 2020-08-15 11:59  潜水的cc  阅读(128)  评论(0)    收藏  举报