数据结构之线性表:动态数组

一、线性表初步认识

1.常见数据结构

在讲线性表之前,我们要先对数据结构有一定的了解
数据结构是计算机存储、组织数据的形式
在这里插入图片描述

常见的数据结构有集合结构、线性结构、树形结构、图形结构

  • 线性结构
    • 数组
    • 链表
    • 队列
    • 哈希表(散列表)
  • 树形结构
    • 二叉树
    • AVL树
    • 红黑树
    • B树
    • Trie
    • 哈夫曼树
    • 并查集
  • 图形结构
    • 邻接矩阵
    • 邻接表

2.线性表

线性表是具有n个相同类型元素的有限序列(n>=0)
在这里插入图片描述

3.数组

  • 数组是一种顺序存储的线性表,所有元素的内存地址是连续的

在这里插入图片描述
数组是申请连续的空间
但是而且一旦申请了空间,那么它的容量就无法改变了,显然不符合我们的要求,我们肯定是希望数组的容量可以根据我们的需求而发生变化,因此,我们可以采取动态数组来解决这种问题

二、动态数组的设计

在这里插入图片描述
在设计相关方法之前,我们先来定义相关属性

  • size:用来表示动态数组里面的元素个数
  • elements:数组
  • DEFAULT_CAPACITY :数组默认容量
  • ELEMENT_NOT_FOUND:没有找到数组中的元素,就返回这个值
    具体的方法在后文介绍
public class ArrayList<E> {
    
    
    /**
     * 元素的数量
     */
    private int size;
    /**
     * 所有的元素
     */
    private E[] elements;

    private static final int DEFAULT_CAPACITY = 10;
    private static final int ELEMENT_NOT_FOUND = -1;
 }

1.构造方法的设计

  • capacity代表的是我们想要给动态数组多少容量
  • 默认容量为10
  • 如果我们给的容量小于默认容量,那么数组的容量就是默认容量
  • 如果我们给的容量大默认容量,那么数组的容量就是我们给的容量
  public ArrayList(int capaticy) {
    
    
        capaticy = (capaticy < DEFAULT_CAPACITY) ? DEFAULT_CAPACITY : capaticy;
        elements = (E[]) new Object[capaticy];
    }

    public ArrayList() {
    
    
        this(DEFAULT_CAPACITY);
    }

2.返回元素个数 size()

 /**
     * 元素的数量
     * @return
     */
    public int size() {
    
    
        return size;
    }

3.判断数组元素是否为空 isEmpty()

  • 数组元素个数为0就代表数组为空
  /**
     * 判断是否为空
     */
    public boolean isEmpty() {
    
    
        return size == 0;
    }

4.查看元素索引 indexOf(E element)

  • 我们可以遍历动态数组,然后把查找的元素和数组里面的元素一一比较
    • 因为数组可以存储任何类型的值,所以可能存储的是对象,我们可以用equals方法来比较
    • 要先判断查找的元素是否为空,因为如果值为空,调用equals方法会出现空指针异常,如果element为空,就使用==
    • 如果不为空,使用equals方法来比较
    /**运行存储null
     * 查看元素的索引
     * @param element
     * @return
     */
    public int indexOf(E element) {
    
    
        if (element == null) {
    
      // 1
            for (int i = 0; i < size; i++) {
    
    
                if (elements[i] == null) return i;
            }
        } else {
    
    
            for (int i = 0; i < size; i++) {
    
    
                if (element.equals(elements[i])) return i; // n
            }
        }
        return ELEMENT_NOT_FOUND;
    }

5.对下标是否合法的判断

    private void outOfBounds(int index) {
    
    
        throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
    }

    private void rangeCheck(int index) {
    
    
        if (index < 0 || index >= size) {
    
    
            outOfBounds(index);
        }
    }

    private void rangeCheckForAdd(int index) {
    
    
        if (index < 0 || index > size) {
    
    
            outOfBounds(index);
        }
    }

6.判断是否需要扩容的方法 ensureCapacity

  • 如果原来的数组容量>=size+1,则不需要扩容
  • 否则需要扩容
  • 这个方法主要是为后面添加元素服务的
 /**
     * 确保有足够容量
     */
    private void ensureCapacity(int capacity) {
    
    
        int oldCapacity = elements.length;
        /**
         * 此时不需要扩容
         */
        if (oldCapacity >= capacity) {
    
    
            return;
        }
        //扩容后,新容量为原来的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        E[] newElements=(E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
    
    
            newElements[i]=elements[i];
        }
        elements=newElements;
        System.out.println(oldCapacity+"扩容为: "+newCapacity);

    }

 

7.添加元素的方法 add

  • 在指定位置添加元素
  • 添加元素时,先判断索引是否合法
  • 然后判断是否需要扩容
  • 然后再进行添加元素
  • 记得size要加1
 /**
     * 在index位置插入一个元素
     * @param index
     * @param element
     */
    public void add(int index, E element) {
    
    
        rangeCheckForAdd(index);

        ensureCapacity(size + 1);

        for (int i = size; i > index; i--) {
    
    
            elements[i] = elements[i - 1];
        }
        elements[index] = element;
        size++;
    }

  • 在数组末尾添加元素
 /**
     * 添加元素到尾部
     * @param element
     */
    public void add(E element) {
    
    
        add(size, element);
    }

8.清除所有元素 clear

    public void clear() {
    
    
        for (int i = 0; i < size; i++) {
    
    
            elements[i] = null;
        }
        size = 0;
    }

9.判断数组是否包含某个元素

  • 因为前面已经有了查看元素索引的方法
  • 如果没有这个元素,返回的是ELEMENT_NOT_FOUND
  • 我们只需要调用indexOf方法就可以进行判断了
  public boolean contains(E element) {
    
    
        return indexOf(element) != ELEMENT_NOT_FOUND;
    }

10获取某个索引位置的元素 get(int index)

   public E get(int index) {
    
    
        rangeCheck(index);
        return elements[index];
    }

11.修改某个索引位置的元素

最后返回修改前的元素值

 public E set(int index, E element) {
    
    
        rangeCheck(index);

        E old = elements[index];
        elements[index] = element;
        return old;
    }

12.删除某个位置的元素 remove

    public E remove(int index) {
    
    
        rangeCheck(index);

        E old = elements[index];
        for (int i = index + 1; i < size; i++) {
    
    
            elements[i - 1] = elements[i];
        }
        elements[--size] = null;
        return old;
    }

13.打印动态数组

    @Override
    public String toString() {
    
    
        // size=3, [99, 88, 77]
        StringBuilder string = new StringBuilder();
        string.append("size=").append(size).append(", [");
        for (int i = 0; i < size; i++) {
    
    
            if (i != 0) {
    
    
                string.append(", ");
            }

            string.append(elements[i]);

//			if (i != size - 1) {
    
    
//				string.append(", ");
//			}
        }
        string.append("]");
        return string.toString();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_52797170/article/details/124491008