「Dart 语言实现」线性表—动态数组

447 阅读1分钟

线性表:

线性表是具有n个相同元素类型的有限序列(n>=0)

线性表—动态数组

线性表一般会有索引 0 1 2 3 .....

a1 是首节点(首元素),an是 尾结点(尾元素)

a1是a2的前驱,a2是a1 的后继

常见的线性表:

数组、链表、栈、队列、哈希表(散列表)

在很多编程语言中,数组都有个致命的缺点:无法动态修改容量。

实际开发中,我们更希望数组的容量是可以动态改变的。

下面自己实现一个动态数组:

// 动态数组
class ArrayList {
  // 元素的数量
  int size = 0;
  // 所有的元素
  List elements = [];

  static const DEFAULT_CAPACITY = 10; // 初始化默认最小容量
  static const ELEMENT_NOT_FOUND = -1; // 没有找到元素

  ArrayList() {
    elements = List.filled(DEFAULT_CAPACITY, null, growable: false);
  }

  ArrayList.array(int capacity) {
    capacity = (capacity < DEFAULT_CAPACITY) ? DEFAULT_CAPACITY : capacity;
    elements = List.filled(capacity, null, growable: false);
  }

  // 清除所有元素
  clear() {
    for (int i = 0; i < size; i++) {
      elements[i] = null;
    }
    size = 0;
  }

  // size(){
  //   return size;
  // }

  // 是否为空
  bool isEmpty() {
    return size == 0;
  }

  // 是否包含某个元素
  bool contains(var element) {
    return indexOf(element) != ELEMENT_NOT_FOUND;
  }

  // 查看元素的索引
  int indexOf(var element) {
    if (element == null) {
      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;
  }

  void add(var element) {
    add2(size, element);
  }

  void add2(int index, var element) {
    rangeCheckForAdd(index);
    ensureCapacity(size + 1);

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

  // 保证要有capacity的容量
  void ensureCapacity(int capacity) {
    int oldCapacity = elements.length;
    if (oldCapacity >= capacity) return;

    // 新容量为旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    List newElements = List.filled(newCapacity, null, growable: false);
    for (int i = 0; i < size; i++) {
      newElements[i] = elements[i];
    }
    elements = newElements;

    print("${oldCapacity}扩容为${newCapacity}");
  }

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

  void outOfBounds(int index) {
    throw new Exception("Index:$index Size:$size");
  }

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

  // 获取index位置的元素
  Object get(int index) {
    rangeCheck(index);
    return elements[index];
  }

  // 设置index位置的元素
  Object set(int index, var element) {
    rangeCheck(index);

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

  // 删除index位置的元素
  Object remove(int index) {
    rangeCheck(index);

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

void add(int index, var element) 方法涉及到数组扩容。

Object remove(int index) 涉及到 元素移动,要好好看一下。

clear() 中释放对象 elements[i] = null; 

其他方法都好理解

更多文章请关注我:

  1. 我的个人今日头条主页:www.toutiao.com/c/user/toke…

  2. 我的微信公众号:

qrcode_for_gh_f8731765bf7c_258.jpg

  1. 我的掘金主页: juejin.cn/user/118789…