数据结构--集合

416 阅读8分钟

什么是集合

集合(set):在计算机科学中,集合是一组可变数量的数据项(也可能是 0 个)的组合。集合通常是由一组无序的,不能重复的元素组成。

ES6 中的 Set 就是一个集合类,这里我们重新封装一个 Set 类,了解集合的底层实现。

集合常用的方法

  • has(value) 判断集合中是否存在 value 值
  • add(value) 往集合中添加 value
  • remove(value) 删除集合中指定的 value
  • clear() 清空集合中所有 value
  • size() 获取集合中的 value 个数
  • values() 获取集合中所有的 value
  • union(otherSet) 求两个集合的并集
  • intersection(otherSet) 求两个集合的交集
  • difference(otherSet) 求两个集合的差集
  • subset() 求两个集合的子集

集合间的操作如下图:

  • 并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。
  • 交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。
  • 差集:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
  • 子集:验证一个给定集合是否是另一个集合的子集。

ES6 实现集合结构

  • 封装集合结构类
/**
 * 集合结构
 *  集合通常是由一组无序的,不能重复的元素构成。
 *  数学中常指的集合中的元素是可以重复的,但是计算机中的集合中的元素不能重复。
 *  集合是特殊的数组
 *   特殊之处在于里面的元素没有顺序也不能重复。
 *   没有顺序意味着不能通过下标值进行访问,不能重复意味着相同的对象在集合中只会存在一份。
 *
 * @class Set_
 */
class Set_ {
  constructor() {
    this.set = {};
  }
}
  • has(value) 方法的实现
// has(value) 判断集合中是否存在 value 值,存在返回 true,否则返回 false
  has(value) {
    return this.set.hasOwnProperty(value);
  }
  • add(value) 方法的实现
// add(value) 往集合中添加 value
  add(value) {
    if (this.has(value)) return false;
    this.set[value] = value;
    return true;
  }

  • remove(value) 方法的实现
  // remove(value) 删除集合中指定的 value
  remove(value) {
    // 如果集合中没有该数据就返回 false
    if (!this.has(value)) return false;
    delete this.set[value];
  }
  • clear() 方法的实现
  // clear() 清空集合中所有 value
  clear() {
    this.set = {};
  }
  • size() 方法的实现
  // size() 获取集合中的 value 个数
  size() {
    return Object.keys(this.set).length;
  }
  • values() 方法的实现
  // values() 获取集合中所有的 value
  values() {
    return Object.keys(this.set);
  }

  • union() 方法的实现
// union() 求两个集合的并集
  union(otherSet) {
    // 1. 首先创建一个新的集合
    const unionSet = new Set_();

    // 2. 将当前集合(this)中的数据全部添加到新的集合(unionSet)中
    for (let data of this.values()) {
      unionSet.add(data);
    }

    // 3. 将其他集合(otherSet)中的数据全部添加到新的集合(unionSet)中
    for (let data of otherSet.values()) {
      unionSet.add(data);
    }

    // 4. 返回这个集合
    return unionSet;
  }
  • intersection() 方法的实现
// intersection() 求两个集合的交集
  intersection(otherSet) {
    // 1. 创建一个新的集合
    const intersectionSet = new Set_();

    // 2. 循环添加数据
    // 遍历从当前集合中取出每一个 value 判断是否在 otherSet 集合中存在
    for (let data of this.values()) {
      if (otherSet.has(data)) {
        intersectionSet.add(data);
      }
    }
    // 返回集合
    return intersectionSet;
  }
  • difference() 方法的实现
 // difference() 差集
  difference(otherSet) {
    // 1. 创建一个新的集合
    const differenceSet = new Set_();

    // 2. 从当前的集合中取出每一个 value 判断是否在 otherSet 集合中,不存在就是差集
    for (let data of this.values()) {
      if (!otherSet.has(data)) {
        differenceSet.add(data);
      }
    }
    // 返回
    return otherSet;
  }
  • subset() 方法的实现
// subset() 子集
  subset(otherSet) {
    // 从当前的集合中取出每一个 value ,判断是否在otherSet集合中存在,有不存在的返回false
    // 循环完毕返回 true
    for (let data of this.values()) {
      if (!otherSet.has(data)) {
        return false;
      }
    }
    return true;
  }

集合结构总体代码

/**
 * 集合结构
 *  集合通常是由一组无序的,不能重复的元素构成。
 *  数学中常指的集合中的元素是可以重复的,但是计算机中的集合中的元素不能重复。
 *  集合是特殊的数组
 *   特殊之处在于里面的元素没有顺序也不能重复。
 *   没有顺序意味着不能通过下标值进行访问,不能重复意味着相同的对象在集合中只会存在一份。
 *
 * @class Set_
 */
class Set_ {
  constructor() {
    this.set = {};
  }

  // 集合结构中的操作方法

  // has(value) 判断集合中是否存在 value 值,存在返回 true,否则返回 false
  has(value) {
    return this.set.hasOwnProperty(value);
  }

  // add(value) 往集合中添加 value
  add(value) {
    if (this.has(value)) return false;
    this.set[value] = value;
    return true;
  }

  // remove(value) 删除集合中指定的 value
  remove(value) {
    // 如果集合中没有该数据就返回 false
    if (!this.has(value)) return false;
    delete this.set[value];
  }

  // clear() 清空集合中所有 value
  clear() {
    this.set = {};
  }

  // size() 获取集合中的 value 个数
  size() {
    return Object.keys(this.set).length;
  }

  // values() 获取集合中所有的 value
  values() {
    return Object.keys(this.set);
  }

  // 集合间的操作
  // 并集: 对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。
  // 交集:对于给定的两个集合,返回一个包含两个集合中共用元素的新集合。
  // 差集:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
  // 子集:验证一个给定的集合是否是另一个集合的子集。

  // union() 求两个集合的并集
  union(otherSet) {
    // 1. 首先创建一个新的集合
    const unionSet = new Set_();

    // 2. 将当前集合(this)中的数据全部添加到新的集合(unionSet)中
    for (let data of this.values()) {
      unionSet.add(data);
    }

    // 3. 将其他集合(otherSet)中的数据全部添加到新的集合(unionSet)中
    for (let data of otherSet.values()) {
      unionSet.add(data);
    }

    // 4. 返回这个集合
    return unionSet;
  }

  // intersection() 求两个集合的交集
  intersection(otherSet) {
    // 1. 创建一个新的集合
    const intersectionSet = new Set_();

    // 2. 循环添加数据
    // 遍历从当前集合中取出每一个 value 判断是否在 otherSet 集合中存在
    for (let data of this.values()) {
      if (otherSet.has(data)) {
        intersectionSet.add(data);
      }
    }
    // 返回集合
    return intersectionSet;
  }

  // difference() 差集
  difference(otherSet) {
    // 1. 创建一个新的集合
    const differenceSet = new Set_();

    // 2. 从当前的集合中取出每一个 value 判断是否在 otherSet 集合中,不存在就是差集
    for (let data of this.values()) {
      if (!otherSet.has(data)) {
        differenceSet.add(data);
      }
    }
    // 返回
    return otherSet;
  }

  // subset() 子集
  subset(otherSet) {
    // 从当前的集合中取出每一个 value ,判断是否在otherSet集合中存在,有不存在的返回false
    // 循环完毕返回 true
    for (let data of this.values()) {
      if (!otherSet.has(data)) {
        return false;
      }
    }
    return true;
  }
}