数组

(一)数组:把数据码成一排进行存放

  1. 索引可以有语意
    1. 数组最好应用于“索引有语意”的情况
    2. 但并非所有有语意的索引都适用于数组,如身份证号
  2. 索引也可以没有语意

1. 数组也可以处理“索引没有语意”的情况(本章节主要处理

(二)封装数组类

  • 声明
    public class Array<E> { //声明成<E>泛型数组
        private E[] data;//private int[] data;
        private int size;
    
        /**
         *
         * @param capacity
         */
        //构造函数,传入数组的容量capacity构造Array
        public Array(int capacity){
            data = (E[]) new Object[capacity];//data = new int[capacity];
            size = 0;
        }
    
        //无参数的构造函数,默认数组的容量capacity = 10
        public Array(){
            this(10);
        }
    
        //获取数组中元素的个数
        public int getSize(){
            return size;
        }
    
        //获取数组的容量
        public int getCapacity(){
            return data.length;
        }
    
        //返回数组是否为空
        public boolean isEmpty(){
            return size == 0;
        }
    
    
    
    /**
     *此处实现增删查改
    */
    
    
        //输出格式
        @Override
        public String toString(){
            StringBuilder res = new StringBuilder();
            res.append(String.format("Array: size = %d, capacity = %d\n",size,data.length));
            res.append('[');
            for (int i = 0; i < size; i++){
                res.append(data[i]);
                if (i != size - 1)
                    res.append(", ");
            }
            res.append(']');
    
            return res.toString();
        }
    
        
    }
    

     

  • 向数组添加元素(增)
    1. 向数组第index个位置添加元素e
      //在第index个位置插入一个新元素e
          public void add(int index, E e){//int e
              if (index < 0 || index > size)
                  throw new IllegalArgumentException("addLast failed. require index >=0 and index < size.");
      
              if (size == data.length)
                  //throw new IllegalArgumentException("addLast failed. Array is full.");
                  resize(2*data.length);//扩容:扩充容器的大小
      
              for (int i = size -1; i >= index; i --)
                  data[i + 1] = data[i];//将index后的所有元素向后/前移动一位,腾出index的位置
      
              data[index] = e;
              size ++;
          }

       

    2. 向数组的第一个位置添加新元素e
       //向数组中添加元素(向所有元素前添加一个新元素)
          public void addFirst(E e){//int e
              add(0,e);//直接调用add方法
          }

       

    3. 向数组的最后一个位置添加新元素e
      //向数组中添加元素(向所有元素后添加一个新元素)
          public void addLast(E e){//int e
              //if (size == data.length)
              // throw new IllegalArgumentException("addLast failed. Array is full.");
      
              //data[size] = e;
              //size ++;
              add(size,e);//直接调用add方法
          }

       

  • 在数组中查询元素(查)
    1. 获取index索引位置的元素
      //获取index索引位置的元素
          public E get(int index){ //int get
              if (index < 0 || index >=size)
                  throw new IllegalArgumentException("get failed. index is illegal.");
              return data[index];
          }

       

    2. 查找数组中元素e所在的索引,如果不存在e,则返回-1
      //查找数组中元素e所在的索引,如果不存在e,则返回-1
          public int find(E e){//int e
              for (int i = 0; i < size; i++){
                  if (data[i].equals(e))//data[i] == e
                      return i;
              }
              return -1;
          }

       

    3. 查找数组中是否有元素e
       //查找数组中是否有元素e
          public boolean contains(E e){//int e
              for (int i = 0; i < size; i++){
                  if (data[i].equals(e))//data[i] == e 引用比较      equals()值比较
                      return true;
              }
              return false;
          }

       

  • 在数组中修改元素(改)
    1. 修改index索引位置的元素为e 
      //修改index索引位置的元素为e
          public void set(int index, E e){//int e
              if (index < 0 || index >=size)
                  throw new IllegalArgumentException("set failed. index is illegal.");
              data[index] = e;
          }

       

  • 在数组中删除元素(删)

                   1. 删除指定index位置元素,并返回删除的元素

 //从数组中删除指定位置index的元素,返回删除的元素
    public E remove(int index){//int remove
        if (index < 0 || index >=size)
            throw new IllegalArgumentException("remove failed. index is illegal.");

        E ret = data[index];
        for(int i = index +1; i < size; i++)
            data[i-1] = data[i];
        size --;
        data[size] = null;//非必须;       loitering objects != memory leak

        if (size == data.length / 4 && data.length / 2 != 0)//为了减少resize()的使用
            // size == data.length / 2.     data.length / 2 !=0保证数组的大小不能为0
            resize(data.length / 2);//减少数组的容量
        return ret;
    }

                   2. 删除数组的第一个元素,返回删除的元素

//删除数组的第一个元素,返回删除的元素
    public E removeFirst(){//int removeFirst
        return remove(0);
    }

                   3. 删除数组中的最后一个元素,返回删除的元素

 //删除数组中的最后一个元素,返回删除的元素
    public E removeLast(){//int removeLast
        return remove(size - 1);
    }

                   4. 从数组中删除元素e

 //从数组中删除元素e
    public void removeElement(E e){//int e
        int index = find(e);
        if (index != -1)
            remove(index);
    }
  • 扩充数组的容量,解决数组空间不够用的问题
    //扩充数组的容量,解决数组空间不够用的问题
        private void resize(int newCapacity){
            E[] newData = (E[]) new Object[newCapacity];
            for (int i = 0; i < size; i++)
                newData[i] = data[i];
            data = newData;
        }

     

(三)使用泛型

  • 让我们输数据结构可以放置“任何”数据类型
  • 不可以是基本数据类型,只能是类对象
    • boolean, byte, char, short, int, long, float, double
  • 每个基本数据类型都有对应的包装类
    • Boolean, Byte, Char, Short,Int, Long, Float, Double

(四)动态数组

//扩充数组的容量,解决数组空间不够用的问题
    private void resize(int newCapacity){
        E[] newData = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++)
            newData[i] = data[i];
        data = newData;
    }

(五)简单的时间复杂度分析

  •  时间复杂度分为:O(1), O(n), O(lgn), O(nlogn), O(n^2),其中O是描述算法的运行时间和输入数据之间的关系
  • 分析动态数组的时间复杂度
    • 添加操作    O(n)     最坏情况是O(n)
      • addLast(e) : O(1)
      • addFirst(e) : O(n)
      • add(index, e) : O(n/2) = O(n)
      • resize() : O(n)
    • 删除操作    O(n)     最坏情况是O(n)
      • removeLast(e) : O(1)
      • removeFirst(e) : O(n)
      • remove(index, e) : O(n/2) = O(n)
      • resize() : O(n)
    • 修改操作    O(1)
      • set(index, e) : O(1)
    • 查找操作
      • get(index) : O(1)
      • contains (e) : O(n)
      • find(e) : O(n)
  • 均摊复杂度分析和防止复杂度震荡  
    • resize()的复杂度分析
      • 添加操作    O(n)     最坏情况是O(n)
        • addLast(e) : O(1)
        • addFirst(e) : O(n)
        • add(index, e) : O(n/2) = O(n)
        • resize() : O(n)
    • 复杂度震荡
      • 同时看addLast和removeLast操作
        • addLast : O(n)
        • removeLast : O(n)
      • 出现问题的原因:removeLast时resize()过于着急
        • 解决方案: Lazy
          if (size == data.length / 4 && data.length / 2 != 0)//为了减少resize()的使用
                      // size == data.length / 2.     data.length / 2 !=0保证数组的大小不能为0
                      resize(data.length / 2);//减少数组的容量

           

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值