JavaScript数据结构与算法之集合(Set)


Posted in Javascript onJanuary 29, 2016

集合(Set)

说起集合,就想起刚进高中时,数学第一课讲的就是集合。因此在学习集合这种数据结构时,倍感亲切。
集合的基本性质有一条: 集合中元素是不重复的。因为这种性质,所以我们选用了对象来作为集合的容器,而非数组。
虽然数组也能做到所有不重复,但终究过于繁琐,不如集合。

集合的操作

集合的基本操作有交集、并集、差集等。这儿我们介绍JavaScipt集合中交集、并集、差集的实现。

JavaScipt中集合的实现

首先,创建一个构造函数。

/**
 * 集合的构造函数
 */
function Set方法 {
 /**
  * 集合元素的容器,以对象来表示
  * @type {Object}
  */
 var items = {};
}

集合需要有如下方法:

  1. has(value): 检测集合内是否有某个元素
  2. add(value): 给集合内添加某个元素
  3. remove(value): 移除集合中某个元素
  4. clear(value): 清空集合
  5. size(): 返回集合长度
  6. values(): 返回集合转换的数组
  7. union(otherSet): 返回两个集合的并集
  8. intersection(otherSet): 返回两个集合的交集
  9. difference(otherSet): 返回两个集合的差集
  10. subset(otherSet): 判断该集合是否为传入集合的子集

has方法:

说明:集合中元素是不重复的。所以在其它任何操作前,必须用has方法确认集合是否有某个元素。这儿使用了hasOwnProperty方法来检测。
实现:

/**
 * 检测集合内是否有某个元素
 * @param {Any} value  要检测的元素
 * @return {Boolean}    如果有,返回true
 */
this.has = function(value) {
 // hasOwnProperty的问题在于
 // 它是一个方法,所以可能会被覆写
 return items.hasOwnProperty(value)
};

add方法:

说明: 给集合内添加某个元素。
实现:

/**
 * 给集合内添加某个元素
 * @param {Any} value 要被添加的元素
 * @return {Boolean}    添加成功返回True。
 */
this.add = function(value) {
 //先检测元素是否存在。
 if (!this.has(value)) {
  items[value] = value;
  return true;
 }
 //如果元素已存在则返回false
 return false;
};

remove方法:

说明: 移除集合中某个元素
实现:

/**
 * 移除集合中某个元素
 * @param {Any} value 要移除的元素
 * @return {Boolean}    移除成功返回True。
 */
this.remove = function(value) {
 //先检测元素是否存在。
 if (this.has(value)) {
  delete items[value];
  return true;
 }
 //如果元素不存在,则删除失败返回false
 return false;
};

clear方法:
说明: 清空集合
实现:

/**
 * 清空集合
 */
this.clear = function() {
 this.items = {};
};

size方法

说明: 返回集合长度,这儿有两种方法。第一种方法使用了Object.keys这个Api,但只支持IE9及以上。第二种则适用于所有浏览器。
实现:

/**
 * 返回集合长度,只可用于IE9及以上
 * @return {Number} 集合长度
 */
this.size = function() {
 // Object.keys方法能将对象转化为数组
 // 只可用于IE9及以上,但很方便
 return Object.keys(items).length;
}

/**
 * 返回集合长度,可用于所有浏览器
 * @return {Number} 集合长度
 */
this.sizeLegacy = function() {
 var count = 0;
 for (var prop in items) {
  if (items.hasOwnProperty(prop)) {
   ++count;
  }
 }
 return count;
}

values方法

说明: 返回集合转换的数组,这儿也有两种方法。理由同上。使用了Object.keys,只能支持IE9及以上。
实现:

/**
 * 返回集合转换的数组,只可用于IE9及以上
 * @return {Array} 转换后的数组
 */
this.values = function() {
 return Object.keys(items);
};

/**
 * 返回集合转换的数组,可用于所有浏览器
 * @return {Array} 转换后的数组
 */
this.valuesLegacy = function() {
 var keys = [];
 for (var key in items) {
  keys.push(key)
 };
 return keys;
};

union方法

说明: 返回两个集合的并集
实现:

/**
 * 返回两个集合的并集
 * @param {Set} otherSet 要进行并集操作的集合
 * @return {Set}     两个集合的并集
 */
this.union = function(otherSet) {
 //初始化一个新集合,用于表示并集。
 var unionSet = new Set();
 //将当前集合转换为数组,并依次添加进unionSet
 var values = this.values();
 for (var i = 0; i < values.length; i++) {
  unionSet.add(values[i]);
 }

 //将其它集合转换为数组,依次添加进unionSet。
 //循环中的add方法保证了不会有重复元素的出现
 values = otherSet.values();
 for (var i = 0; i < values.length; i++) {
  unionSet.add(values[i]);
 }

 return unionSet;
};

intersection方法

说明: 返回两个集合的交集
实现:

/**
 * 返回两个集合的交集
 * @param {Set} otherSet 要进行交集操作的集合
 * @return {Set}     两个集合的交集
 */
this.intersection = function(otherSet) {
 //初始化一个新集合,用于表示交集。
 var interSectionSet = new Set();
 //将当前集合转换为数组
 var values = this.values();
 //遍历数组,如果另外一个集合也有该元素,则interSectionSet加入该元素。
 for (var i = 0; i < values.length; i++) {

  if (otherSet.has(values[i])) {
   interSectionSet.add(values[i])
  }
 }

 return interSectionSet;
};

difference方法

说明: 返回两个集合的差集
实现:

/**
 * 返回两个集合的差集
 * @param {Set} otherSet 要进行差集操作的集合
 * @return {Set}     两个集合的差集
 */
this.difference = function(otherSet) {
 //初始化一个新集合,用于表示差集。
 var differenceSet = new Set();
 //将当前集合转换为数组
 var values = this.values();
 //遍历数组,如果另外一个集合没有该元素,则differenceSet加入该元素。
 for (var i = 0; i < values.length; i++) {

  if (!otherSet.has(values[i])) {
   differenceSet.add(values[i])
  }
 }

 return differenceSet;
};

subset方法

说明: 判断该集合是否为传入集合的子集。这段代码在我自己写完后与书上一比对,觉得自己超级low。我写的要遍历数组三次,书上的只需要一次,算法复杂度远远低于我的。
实现:

/**
 * 判断该集合是否为传入集合的子集
 * @param {Set} otherSet 传入的集合
 * @return {Boolean}   是则返回True
 */
this.subset = function(otherSet) {
 // 第一个判定,如果该集合长度大于otherSet的长度
 // 则直接返回false
 if (this.size() > otherSet.size()) {
  return false;
 } else {
  // 将当前集合转换为数组
  var values = this.values();

  for (var i = 0; i < values.length; i++) {

   if (!otherSet.has(values[i])) {
    // 第二个判定。只要有一个元素不在otherSet中
    // 那么则可以直接判定不是子集,返回false
    return false;
   }
  }

  return true;
 }
};

ES6中的集合

ES6也提供了集合,但之前看ES6的集合操作一直迷迷糊糊的。实现一遍后再去看,感觉概念清晰了很多。
具体的我掌握的不是很好,还在学习中,就不写出来啦~推荐看阮一峰老师的《ECMAScript 6入门》中对ES6 Set的介绍。
《ECMAScript 6入门》? Set和Map数据结构

感想

到了这儿,已经掌握了一些基本的数据结构。剩下的都是难啃的骨头了(对我而言)。

字典的散列表、图、树、排序算法。算是四大金刚,所以近期关于数据结构与算法系列的文章,可能会更新的很慢。对我来说,也算是一个坎。希望这个寒假,能跨过这个坎。

Javascript 相关文章推荐
javascript indexOf函数使用说明
Jul 03 Javascript
GreyBox技术总结(转)
Nov 23 Javascript
jquery 使用点滴函数代码
May 20 Javascript
Javascript实现商品秒杀倒计时(时间与服务器时间同步)
Sep 16 Javascript
window.onerror()的用法与实例分析
Jan 27 Javascript
使用pcs api往免费的百度网盘上传下载文件的方法
Mar 17 Javascript
关于javascript sort()排序你可能忽略的一点理解
Jul 18 Javascript
vue插件开发之使用pdf.js实现手机端在线预览pdf文档的方法
Jul 12 Javascript
详解vscode中vue代码颜色插件
Oct 11 Javascript
webpack HappyPack实战详解
Oct 08 Javascript
Element实现表格嵌套、多个表格共用一个表头的方法
May 09 Javascript
JavaScript中使用Spread运算符的八种方法总结
Jun 18 Javascript
AngularJS 使用 UI Router 实现表单向导
Jan 29 #Javascript
JavaScript数据结构与算法之链表
Jan 29 #Javascript
动态创建按钮的JavaScript代码
Jan 29 #Javascript
JavaScript数据结构与算法之栈与队列
Jan 29 #Javascript
javascript实现表单验证
Jan 29 #Javascript
jQuery实现横向带缓冲的水平运动效果(附demo源码下载)
Jan 29 #Javascript
JavaScript判断DIV内容是否为空的方法
Jan 29 #Javascript
You might like
967 个函式
2006/10/09 PHP
使用eAccelerator加密PHP程序
2008/10/03 PHP
php 高效率写法 推荐
2010/02/21 PHP
PHP禁止页面缓存的代码
2011/10/23 PHP
php使用Smarty的相关注意事项及访问变量的几种方式
2011/12/08 PHP
PHP代码优化之成员变量获取速度对比
2014/02/28 PHP
php慢查询日志和错误日志使用详解
2021/02/27 PHP
Google Suggest ;-) 基于js的动态下拉菜单
2006/10/11 Javascript
JS getMonth()日期函数的值域是0-11
2010/02/15 Javascript
JQuery $.each遍历JavaScript数组对象实例
2014/09/01 Javascript
Javascript数组与字典用法分析
2014/12/13 Javascript
简介JavaScript中toUpperCase()方法的使用
2015/06/06 Javascript
深入浅析Extjs中store分组功能的使用方法
2016/04/20 Javascript
Javascript获取图片原始宽度和高度的方法详解
2016/09/20 Javascript
JS实现Ajax的方法分析
2016/12/20 Javascript
JS绘制微信小程序画布时钟
2016/12/24 Javascript
在 Angular2 中实现自定义校验指令(确认密码)的方法
2017/01/23 Javascript
微信小程序的分类页面制作
2017/06/27 Javascript
一个Js文件函数中调用另一个Js文件函数的方法演示
2017/08/14 Javascript
微信小程序实现横向增长表格的方法
2018/07/24 Javascript
CKEditor4配置与开发详细中文说明文档
2018/10/08 Javascript
ES2020 已定稿,真实场景案例分析
2020/05/25 Javascript
JavaScript中变量提升和函数提升的详解
2020/08/07 Javascript
jquery实现点击左右按钮切换图片
2021/01/27 jQuery
python实现apahce网站日志分析示例
2014/04/02 Python
python3编写C/S网络程序实例教程
2014/08/25 Python
举例讲解Python中metaclass元类的创建与使用
2016/06/30 Python
python实现百度语音识别api
2018/04/10 Python
matplotlib实现区域颜色填充
2019/03/18 Python
Python3 使用selenium插件爬取苏宁商家联系电话
2019/12/23 Python
CSS3 transform的skew属性值图文详解
2014/07/21 HTML / CSS
亚洲最大旅游体验平台:KKday
2017/10/21 全球购物
财务经理的岗位职责
2013/12/17 职场文书
幼儿园毕业园长感言
2014/02/24 职场文书
婚礼答谢宴主持词
2014/03/14 职场文书
导游词怎么写
2015/02/04 职场文书