美文网首页
数据结构——集合

数据结构——集合

作者: 柏丘君 | 来源:发表于2018-02-16 11:11 被阅读0次

    集合也是一种常见的数据结构,在 ES6 中已经原生支持了这种数据结构 Set。集合是一种无序、且不能有重复元素的数据结构。
    集合有如下常用操作:

    1. 添加元素
    2. 移除元素
    3. 判断元素是否存在
    4. 清空集合
    5. 获取集合的长度
    6. 获取集合的并集、交集、差集

    集合的代码实现

    下面是集合的代码实现,首先进行接口定义 IMySet

    interface IMySet<T>{
        // 向集合中添加元素
        add(ele:T):void;
        // 从集合中移除元素
        remove(ele:T):T;
        // 判断集合中是否拥有某个元素
        has(ele:T):boolean;
        // 清空集合
        clear():void;
        // 获取集合的长度
        size():number;
        // 获取集合中的元素
        toString():T[];
        // 获取并集
        getUnionSet(newSet:IMySet<T>):IMySet<T>;
        // 获取交集
        getIntersectionSet(newSet:IMySet<T>):IMySet<T>;
        // 获取差集
        getDifferenceSet(newSet:IMySet<T>):IMySet<T>;
        // 判断是否是子集
        isSubset(parSet:IMySet<T>):boolean;
    }
    

    下面实现 MySet 类:

    class MySet<T> implements IMySet<T>{
        private dataStore:{
            [propName:string]:T
        } = {};
        private _size:number = 0;
        add(ele:T):void{
            // 判断该元素是否存在
            if(!this.has(ele)){
                // 获取字符串的键值
                const key:string = ele.toString();
                this.dataStore[key] = ele;
                this._size++;
            }
        }
        remove(ele:T):T{
            // 获取字符串的键值
            const key:string = ele.toString();
            // 获取元素
            const val:T = this.dataStore[key];
            // 删除 dataStore 上的键
            delete this.dataStore[key]
            this._size--;
            return val;
        }
        has(ele:T):boolean{
            const key:string = ele.toString();
            // 通过 hasOwnProperty 方法判断集合中是否存在某个值
            return this.dataStore.hasOwnProperty(key);
        }
        size():number{
            return this._size;
        }
        clear():void{
            // 情况集合
            this.dataStore = {};
        }
        toString():T[]{
            // 遍历 dataStore 中的所有键值
            const res:T[] = Object.keys(this.dataStore).map(v => this.dataStore[v]);
            return res;
        }
        // 获取并集
        getUnionSet(newSet:IMySet<T>):IMySet<T>{
            const 
                // 新建空集合
                tmp:IMySet<T> = new MySet<T>(),
                // 获取新集合中的所有值
                newSetVals:T[] = newSet.toString(),
                // 获取当前集合中的所有值
                currentSetVals:T[] = this.toString();
            // 遍历新集合
            newSetVals.forEach(v => {
                tmp.add(v);
            })
    
            // 遍历当前集合
            currentSetVals.forEach(v => {
                tmp.add(v);
            })
    
            return tmp;
        }
        // 获取交集
        getIntersectionSet(newSet:IMySet<T>):IMySet<T>{
            const 
                // 新建空集合
                tmp:IMySet<T> = new MySet<T>(),
                // 获取新集合中的所有值
                newSetVals:T[] = newSet.toString();
    
            newSetVals.forEach(v => {
                if(this.has(v)){
                    tmp.add(v);
                }
            })
            return tmp;
        }
        // 获取差集
        getDifferenceSet(newSet:IMySet<T>):IMySet<T>{
            const 
                // 新建空集合
                tmp:IMySet<T> = new MySet<T>(),
                // 获取新集合中的所有值
                newSetVals:T[] = newSet.toString();
    
            newSetVals.forEach(v => {
                if(!this.has(v)){
                    tmp.add(v);
                }
            })
            return tmp;
        }
        // 判断是否是子集
        isSubset(parSet:IMySet<T>):boolean{
            const 
                // 获取父集合的所有元素
                parSetVals:T[] = parSet.toString(),
                // 获取当前集合的所有元素
                currentSetVals:T[] = this.toString();
            
            let res:boolean = false;
            if(parSet.size() >= this.size()){
                // 判断当前集合中的元素是否都存在于父集合中
                res = currentSetVals.every(v => parSet.has(v))
            }
            return res;
        }
    }
    

    集合实现原理浅析

    在 ES6 的 Set 出现以前,主要借助 JavaScript 中的对象实现。集合的实现原理:当向集合中添加元素时(调用 add() 方法),在对象中创建一个和新增元素对应的键,值就是新增的元素。
    使用对象模拟的集合大概是这样:

    {
      "A":"A",
      "B":"B",
      "C":"C",
      ...
    }
    

    由于 JavaScript 对象的限制只能使用字符串或者数字作为键,在向集合中添加复杂的数据结构时,需要将这些数据结构转换为字符串添加到对象中。因此下面的代码,只有第一个 add() 方法调用生效:

    const set = new MySet<{name:string}>();
    set.add({name:"MIKE"})
    set.add({name:"JERRY"})
    set.add({name:"PENNY"})
    

    上面的调用结果中,集合中只有一个元素:{name:"MIKE"},且集合的键为:[object Object]
    为了解决这个问题,可以在添加元素时使用差异化的键,这就要求对不同的元素求一个独特的特征值,这有点像散列的做法,当然这是我个人的想法,对于集合肯定还有其他的实现,如果您有其他的方案,可以在评论区留言。

    完。

    相关文章

      网友评论

          本文标题:数据结构——集合

          本文链接:https://www.haomeiwen.com/subject/hhmktftx.html