(一) 数据结构之数组

数组存放

将数据排列成一排存放

注意

数组的下标, 在计算机领域中是从0开始的

数组最大的优点

快速索引

基础使用代码

package com.company;

public class Main {

    public static void main(String[] args) {
        // 创建数组
        int[] scores = new int[10];
        int[] scores2 = new int[]{40, 62, 72, 99}; // 创建数组的时候付初始值
        // 数组赋值
        for (int i = 0; i < 10; i++) {
            scores[i] = i;
        }

        // 数组遍历
        for (int i = 0; i < 10; i++) {
            System.out.println(scores[i]);
        }
        // 增强for循环遍历
        for (int score : scores) {
            System.out.println(score);
        }
    }
}

封装自己的动态数组类

增加元素

对于数组来说, 添加指定位置的一个元素的时候, 只需要将从指定位置的元素到末尾的元素, 统统往后移动一个元素位置, 然后将添加的指定元素添加到指定位置即可. 同时, 需要维护一下size ( size是数组中元素的个数)

获取和修改元素

直接修改指定下标即可

删除元素

与添加元素原理差不多, 只是删除的时候, 将index后面的所有元素均前移一个元素位置, 则将要删除的元素覆盖了. 即达到删除的目的. 同时, 不要忘记size要减一.

修改元素

直接更改指定下标的元素即可, 但是一定要记得限制下标, 不能出现不合法的下标

查询元素

遍历数组查询元素即可

普遍性

使用泛型使数组能够存放一些自定义类

动态性

每当存放数据将要大于容器的时候, 建立新的大于原来数组的数组, 成为新的容器

删除一个元素的时候, 判断size是否小于原来数组长度的1/2, 如果是, 新建一个长度为1/2的数组作为容器

复杂度分析

O(1), O(n), O(lgn), O(nlogn), O(n^2)

大O是描述的是算法的运行时间和输入数据之间的关系

算法运行时间大致和输入数据之间存在线性关系, 但是在分析的时候是忽略常数的. 比如实际时间T=c1*n+2, 我们忽略常数, 认为算法时间复杂度为O(n)

添加和删除操作

  • addLast(e) O(1) 添加resize()操作 O(n) 因为考虑到最坏情况, 所以整体来说, 我们是O(n)级别的操作
  • addFirst(e) O(n)
  • add(index, e) O(n/2) = O(n)

修改操作

  • set(index, e) O(1)

查找操作

  • get(e) O(1)
  • contain(e) O(n)
  • find(e) O(n)

扩容操作

  • resize() O(n)

均摊复杂度

由于resize操作在addLast和removeLast不是每次调用的时候都会触发, 那么可以将resize均摊到每次操作中去,

比如 容器容量为10, 那么添加10次操作, 会触发一次resize, resize会进行10次循环拷贝到新的数组. 将resize的10次操作, 均摊到每次添加的操作中, 那么, 添加一个元素, 就相当于进行了两次基本操作.这样看起来, addLast和removeLast都是O(1)级别的操作

代码

package pers.jssd.array;

/**
 * @author jssd
 * Create 2019-07-21 8:24
 */
public class Array<E> {
   private E[] data; // 数组的存储数据
   private int size; // 数据实际存储的数据大小

   /**
    * 构造函数, 构造数组的初始容量
    *
    * @param capacity 初始的容量大小
    */
   @SuppressWarnings("unchecked")
   public Array(int capacity) {
      data = (E[]) new Object[capacity];
      size = 0;
   }

   /**
    * 默认构造, 初始容量默认为10
    */
   public Array() {
      this(10);
   }

   /**
    * 取得数组的容量大小
    *
    * @return int 数组的容量
    */
   public int getCapactiy() {
      return data.length;
   }

   /**
    * 取得数组存储的数据大小
    *
    * @return 数组存储的数据大小
    */
   public int getSize() {
      return size;
   }

   /**
    * 查看数组是否为空
    *
    * @return 如果为空true, 如果不为空false
    */
   public boolean isEmpty() {
      return size == 0;
   }

   /**
    * 向指定位置添加一个元素
    *
    * @param index 添加元素的位置
    * @param e     要添加的元素
    */
   public void add(int index, E e) {

      if (index < 0 || index > size) {
         throw new IllegalArgumentException("add fall, index is error");
      }
      if (index == data.length) {
         resize(data.length * 2);
      }
      // 将每个元素从index开始, 向后拷贝一个位置
      System.arraycopy(data, index, data, index + 1, size - index);
      data[index] = e;
      size++;
   }

   /**
    * 向末尾添加元素
    *
    * @param e 添加的元素
    */
   public void addLast(E e) {
      add(size, e);
   }

   /**
    * 向开头添加元素
    *
    * @param e 添加的元素
    */
   public void addFirst(E e) {
      add(0, e);
   }

   /**
    * 获取指定位置的元素
    *
    * @param index 获取元素的位置
    * @return 返回获取的指定元素
    */
   public E get(int index) {
      if (index < 0 || index >= size)
         throw new IllegalArgumentException("get fall, index is error");

      return data[index];
   }

   /**
    * 修改指定位置的元素
    *  @param index 修改元素的位置
    * @param e     修改指定元素新的值
    */
   public void set(int index, E e) {
      if (index < 0 || index >= size) {
         throw new IllegalArgumentException("set error, index is error");
      }
      data[index] = e;
   }

   /**
    * 查找元素的索引
    *
    * @param e 查找的元素
    * @return -1如果没有找到, 找到则返回相应的索引
    */
   public int find(E e) {
      for (int i = 0; i < size; i++) {
         if (data[i].equals(e)) {
            return i;
         }
      }
      return -1;
   }

   /**
    * 查看元素在数组中是否存在
    *
    * @param e 查看的元素
    * @return true则元素存在, false则元素不存在
    */
   public boolean contain(E e) {
      int index = find(e);
      return index != -1;
   }

   /**
    * 删除指定位置的元素
    *
    * @param index 要删除的元素位置
    * @return 删除的元素
    */
   public E remove(int index) {
      if (index < 0 || index >= size) {
         throw new IllegalArgumentException("remove fall, index is error");
      }
      E ref = data[index];
      System.arraycopy(data, index + 1, data, index, size - index - 1);
      size--;
      if (size == data.length / 4 && data.length / 2 != 0) {
         resize(data.length / 2);
      }

      return ref;
   }

   /**
    * 删除最后的元素
    *
    * @return 删除的元素
    */
   public E removeLast() {
      return remove(size - 1);
   }

   /**
    * 删除第一个元素
    *
    * @return 删除的元素
    */
   public E removeFirst() {
      return remove(0);
   }

   /**
    * 删除数组中第一次出现的指定元素
    *
    * @param e 删除的元素
    * @return true删除成功, false 删除失败
    */
   public boolean removeElement(E e) {
      int index = find(e);
      if (index != -1) {
         remove(index);
         return true;
      }
      return false;
   }

   /**
    * 删除所有指定的元素
    * @param e 要删除的元素
    * @return 返回删除元素的个数, 如果为0, 则没有删除任何元素
    */
   public int removeAllElement(E e){
      int index = find(e);
      int count = 0;
      while (index != -1) {
         remove(index);
         count ++;
         index = find(e);
      }
      return count;
   }

   /**
    * 对数组进行扩容操作
    * @param newCapacity 新的容量
    */
   @SuppressWarnings("unchecked")
   private void resize(int newCapacity) {
      E[] newData = (E[]) new Object[newCapacity];
      if (size >= 0) System.arraycopy(data, 0, newData, 0, size);
      data = newData;
   }

   @Override
   public String toString() {
      StringBuilder sb = new StringBuilder();
      sb.append("Array: size = ").append(size).append(", capacity = ").append(data.length).append("\n");
      sb.append("[");
      for (int i = 0; i < size; i++) {
         sb.append(data[i]);
         if (i != size - 1) {
            sb.append(", ");
         }
      }
      sb.append("]");

      return sb.toString();
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值