> 文档中心 > 数据结构之线性表:动态数组

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

文章目录

  • 一、线性表初步认识
    • 1.常见数据结构
    • 2.线性表
    • 3.数组
  • 二、动态数组的设计
    • 1.构造方法的设计
    • 2.返回元素个数 size()
    • 3.判断数组元素是否为空 isEmpty()
    • 4.查看元素索引 indexOf(E element)
    • 5.对下标是否合法的判断
    • 6.判断是否需要扩容的方法 ensureCapacity
    • 7.添加元素的方法 add
    • 8.清除所有元素 clear
    • 9.判断数组是否包含某个元素
    • 10获取某个索引位置的元素 get(int index)
    • 11.修改某个索引位置的元素
    • 12.删除某个位置的元素 remove
    • 13.打印动态数组

一、线性表初步认识

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();    }}