学习javascript数据结构(三)——集合

前言

总括: 本文讲解了数据结构中的[集合]概念,并使用javascript实现了集合。

人生多风雨,何处无险阻。

正文

集合简介

在上一篇学习javascript数据结构(二)——链表中我们说了链表这种数据结构,但归根结底,不论是栈,队列亦或是链表都是线性结构。他们都是一种很规矩的数据结构,就像幼儿园的小朋友排队乖乖的站在那不会动一样。


幼儿园小朋友排队

然而纷杂的数据并不会总是排队站在那里,幼儿园小朋友一旦下了课那可就撒欢了,乱糟糟一团。可我们的幼儿园老师却能分辨出这些小朋友,因为啥?因为每个小朋友都在一个班里,而且每一个小朋友都有自己的名字。老师自然很容易就找到小朋友了。


幼儿园小朋友下课

而本篇博文要说的集合正是一堆乱糟糟的数据,唯一的共同点是这些数据隶属于同一个集合,看下百科给出的解释:

由一个或多个元素所构成的叫做集合。

此处的元素就是小朋友了,他们所在的集合就是他们的班级。其实我们在高中的时候也接触过集合的概念。那时候还没有套路这个名词,单纯的岁月,那个年代对于集合是这么解释的:

集合是指具有某种特定性质的具体的或抽象的对象汇总成的集体,这些对象称为该集合的元素。

然后又是这么分类的:

  • 空集:{}
  • 有限集:{a,b,4}
  • 无限集:{1,2,3,4...}

不过,数据结构中集合是没有无限集这个概念的。再然后那时候的集合还有这么几个特性:

  • 确定性:给定一个集合,任给一个元素,该元素或者属于或者不属于该集合,二者必居其一,不允许有模棱两可的情况出现。
  • 互异性:一个集合中,任何两个元素都认为是不相同的,即每个元素只能出现一次。有时需要对同一元素出现多次的情形进行刻画,可以使用多重集,其中的元素允许出现多次。
  • 无序性:一个集合中,每个元素的地位都是相同的,元素之间是无序的。集合上可以定义序关系,定义了序关系后,元素之间就可以按照序关系排序。但就集合本身的特性而言,元素之间没有必然的序。

想当年哥还是个数学学霸,如今却沦落为了一个码农......真是让人唏嘘啊。咳咳!接着说:

集合还有这几种常见的基本操作:

  • 并集
  • 交集
  • 差集

而且我们数据结构中的集合基本是也符合高中时候的数学中的概念的。接下来我们是用ES5来实现集合,为啥子这么说呢......因为在ES6中已经新给出了Set,Map等几个集合类,更加方便快捷的锁定键值对。

集合的创建

首先我们先声明一个集合类:

function(){
    var items={};
}

接下来,我们需要给链表声明一些方法:

  • add(value):向集合添加一个新的项
  • remove(value):从集合移除一个值
  • has(value):如果值在集合中,返回true,否则返回false
  • clear():移除集合中的所有项
  • size():返回集合所包含的元素数量,与数组的length属性相似
  • values():返回一个集合中所有值的数组
  • union(setName):并集,返回包含两个集合所有元素的新集合(元素不重复)
  • intersection(setName):交集,返回包含两个集合中共有的元素的集合、
  • difference(setName):差集,返回包含所有存在本集合而不存在setName集合的元素的新集合
  • subset(setName):子集,验证setName是否是本集合的子集

下面是Set类的完整代码:

function Set() {
    let items = {};
    this.add = function(value){
        if (!this.has(value)){
            items[value] = value;
            return true;
        }
        return false;
    };
    this.delete = function(value){
        if (this.has(value)){
            delete items[value];
            return true;
        }
        return false;
    };
    this.has = function(value){
        return items.hasOwnProperty(value);
        //return value in items;
    };

    this.clear = function(){
        items = {};
    };
    /**
     * Modern browsers function
     * IE9+, FF4+, Chrome5+, Opera12+, Safari5+
     * @returns {Number}
     */
    this.size = function(){
        return Object.keys(items).length;
    };

    /**
     * cross browser compatibility - legacy browsers
     * for modern browsers use size function
     * @returns {number}
     */
    this.sizeLegacy = function(){
        let count = 0;
        for(let key in items) {
            if(items.hasOwnProperty(key))
                ++count;
        }
        return count;
    };
    /**
     * Modern browsers function
     * IE9+, FF4+, Chrome5+, Opera12+, Safari5+
     * @returns {Array}
     */
    this.values = function(){
        let values = [];
        for (let i=0, keys=Object.keys(items); i<keys.length; i++) {
            values.push(items[keys[i]]);
        }
        return values;
    };
    this.valuesLegacy = function(){
        let values = [];
        for(let key in items) {
            if(items.hasOwnProperty(key)) {
                values.push(items[key]);
            }
        }
        return values;
    };
    this.getItems = function(){
      return items;
    };
    this.union = function(otherSet){
        let unionSet = new Set();
        let values = this.values();
        for (let i=0; i<values.length; i++){
            unionSet.add(values[i]);
        }
        values = otherSet.values();
        for (let i=0; i<values.length; i++){
            unionSet.add(values[i]);
        }
        return unionSet;
    };
    this.intersection = function(otherSet){
        let intersectionSet = new Set();
        let values = this.values();
        for (let i=0; i<values.length; i++){
            if (otherSet.has(values[i])){
                intersectionSet.add(values[i]);
            }
        }
        return intersectionSet;
    };
    this.difference = function(otherSet){
        let differenceSet = new Set();
        let values = this.values();
        for (let i=0; i<values.length; i++){
            if (!otherSet.has(values[i])){    
                differenceSet.add(values[i]);
            }
        }
        return differenceSet;
    };
    this.subset = function(otherSet){
        if (this.size() > otherSet.size()){
            return false;
        } else {
            let values = this.values();
            for (let i=0; i<values.length; i++){
                if (!otherSet.has(values[i])){  
                    return false;
                }
            }
            return true;
        }
    };
}

下面是ES6版本代码:

let Set2 = (function () {
    const items = new WeakMap();
    class Set2 {
        constructor () {
            items.set(this, {});
        }
        add(value){
            if (!this.has(value)){
                let items_ = items.get(this);
                items_[value] = value;
                return true;
            }
            return false;
        }
        delete(value){
            if (this.has(value)){
                let items_ = items.get(this);
                delete items_[value];
                return true;
            }
            return false;
        }
        has(value){
            let items_ = items.get(this);
            return items_.hasOwnProperty(value);
        }
        clear(){
            items.set(this, {});
        }
        size(){
            let items_ = items.get(this);
            return Object.keys(items_).length;
        }
        values(){
            let values = [];
            let items_ = items.get(this);
            for (let i=0, keys=Object.keys(items_); i<keys.length; i++) {
                values.push(items_[keys[i]]);
            }
            return values;
        }
        getItems(){
            return items.get(this);
        }
        union(otherSet){
            let unionSet = new Set();
            let values = this.values();
            for (let i=0; i<values.length; i++){
                unionSet.add(values[i]);
            }
            values = otherSet.values();
            for (let i=0; i<values.length; i++){
                unionSet.add(values[i]);
            }
            return unionSet;
        }
        intersection(otherSet){
            let intersectionSet = new Set();
            let values = this.values();
            for (let i=0; i<values.length; i++){
                if (otherSet.has(values[i])){
                    intersectionSet.add(values[i]);
                }
            }
            return intersectionSet;
        }
        difference(otherSet){
            let differenceSet = new Set();
            let values = this.values();
            for (let i=0; i<values.length; i++){
                if (!otherSet.has(values[i])){
                    differenceSet.add(values[i]);
                }
            }
            return differenceSet;
        };
        subset(otherSet){
            if (this.size() > otherSet.size()){
                return false;
            } else {
                let values = this.values();
                for (let i=0; i<values.length; i++){
                    if (!otherSet.has(values[i])){
                        return false;
                    }
                }
                return true;
            }
        };
    }
    return Set2;
})();

后记

集合是一种比较常见的数据结构,在JS中我们已经有了一种类似哈希表的东西:Object(对象)。但现在我们所说的集合只是以[value,value]形式存储数据,下一节我们使用[键,值]形式存储数据,和本文集合的实现略有不同。敬请期待:[学习javascript数据结构(四)——散列表]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,622评论 18 399
  • 4.29 假期出游非我本意... 酒店:挨近轮渡 第一站:椰风寨(深圳湾+大梅沙的集合体),拍婚纱的人超多 ...
    一路李花开阅读 138评论 0 0
  • 今天家里发生了一点事,一整天精神不定,很久没有这种感觉,心里特难受,憋得难受,朋友生日 大白天约去唱歌,所以就去了...
    罗新美阅读 110评论 0 0
  • 刚忙完孩子就这个点了,还有很多事情没做,比如我的作业,单位的一篇通知作业……感觉压力山大!好想自己心中有许多墨水,...
    kitty2017阅读 145评论 0 0
  • 今天在朋友圈看到这样一个动态。 长到这么大 我说不出来我最爱的一部电影 说不出来我最爱的一首歌 说不出来我最爱的一...
    無叶游名阅读 489评论 0 1