javascript数据结构 -- 集合

156 阅读2分钟

集合

1. 定义

  • 集合通常是由一组无序的,不能重复的元素构成.通常使用哈希表实现.
  • 可以将集合看成是一个特殊的数组,但是其无序性又意味着它其中的元素不能通过下标访问.

2. js中的集合

  • 在2015年6月,ES6中已经包含了Set类
  • js中的Object.keys本身就是一个集合

3. 手动实现

3.1 集合中常见的操作

1. add(value): 向集合中添加一个新的项  
2. remove(value): 从集合中移除一个项  
3. has(value): 判断某项是否在集合中  
4. clear(): 移除集合中的所有项  
5. size(): 返回集合元素的数量  
6. values(): 将集合中的元素以数组的方式返回  
7. 其他不常用的方法,暂不实现  

3.2 各个方法的实现: (使用js中键值相等的obj实现集合)

class _Set<T extends string> {  
    items = {} as Record<PropertyKey, any>;  
  
    // 向集合中添加新的项  
    add(ele: T): boolean {  
        if(this.has(ele)){  
            return false  
        }  
        this.items[ele] = ele;  
        return true;  
    }  
  
    // 判断元素是否在集合中  
    has(ele: T): boolean {  
        return this.items.hasOwnProperty(ele);  
    }  
  
    // 删除集合中的某一项  
    remove(ele: T): boolean {  
        if(!this.has(ele)){  
            return false;  
        }  
        delete this.items[ele];  
        return true;  
    }  
  
    // 清空所有的元素  
    clear(): void {  
        this.items = {};  
    }  
  
    // 返回集合中元素的个数  
    size(): number {  
        return Object.keys(this.items).length;  
    }  
  
    // 将集合中的元素以数组的方式返回  
    values(): Array<T> {  
        return Object.values(this.items);  
    }  
}  

3.3 集合之间的操作

  1. 并集(union): 取出两个集合中的元素分别一次添加到新的作为返回值的集合中去;

  2. 交集(intersect): 遍历本集合中的每一个元素,如果传入的参数集合中也有这个元素则将这个元素添加到作为返回值的新的集合中去;

  3. 差集(diff): 遍历本集合中的每一个元素,如果传入的参数集合中没有这个元素则将这个元素添加到作为返回值的新的集合中去;与交集的实现仅有一个符号的差别!

  4. 子集(subset): 判断参数集合是否为本集合的子集;使用已有的方法--传入的参数集合与本集合做差集,如果差集集合的size为0,则证明是子集.

3.4 集合之间的操作实现

    // 和其他集合取并集  
    union(otherSet: _Set<T>): _Set<T> {  
        const unionSet = new _Set<T>();  
        const _v1 = this.values();  
        const _v2 = otherSet.values();  
        [..._v1, ..._v2].forEach(  
            v => {  
                unionSet.add(v);  
            }  
        )  
        return unionSet;  
    }  
  
    // 和其它集合取交集  
    intersect(otherSet: _Set<T>): _Set<T> {  
        const intersectSet = new _Set<T>();  
        const _v1 = this.values();  
        const _v2 = otherSet.values();  
        _v1.forEach(  
            v => {  
                if(_v2.includes(v)) intersectSet.add(v);  
            }  
        )  
  
        return intersectSet;  
    }  
  
    // 和其它集合取差集  
    diff(otherSet: _Set<T>): _Set<T> {  
        const intersectSet = new _Set<T>();  
        const _v1 = this.values();  
        const _v2 = otherSet.values();  
        _v1.forEach(  
            v => {  
                if(!_v2.includes(v)) intersectSet.add(v);  
            }  
        )  
  
        return intersectSet;  
    }  
  
    // 判断传入是否是子集  
    subSet(otherSet: _Set<T>): boolean {  
        const intersectSet = otherSet.diff(this);  
        return intersectSet.size() === 0;  
    }