JavaScript数据结构与算法(八) 集合(ECMAScript 6中定义的类似的Set类)
// 特性:
// 1. 集合是由一组无序且唯一(即不能重复)的项组成的。这个数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中。
// 2. 也可以把集合想象成一个既没有重复元素,也没有顺序概念的数组
// 3. 在数学中,集合也有并集、交集、差集等基本操作。在这一章中我们也会介绍这些操作 // 集合操作
// 并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合
// 并集的数学概念,集合A和B的并集,表示为A∪B,定义如下:
// A∪B = { x | x ∈ A∨x ∈ B }
// 意思是x(元素)存在于A中,或x存在于B中。下图展示了并集操作:
// 并集.png // 交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合
// 交集的数学概念,集合A和B的交集,表示为A∩B,定义如下:
// A∩B = { x | x ∈ A∧x ∈ B }
// 意思是x(元素)存在于A中,且x存在于B中。下图展示了交集操作:
// 交集.png // 差集:对于给定的两个集合,返回一个包含所有存在与第一个集合且不存在与第二个集合的元素的新集合
// 差集的数学概念,集合A和B的差集,表示为AB,定义如下:
// AB = { x | x ∈ A ∧ x B }
// 意思是x(元素)存在于A中,且x不存在于B中。下图展示了集合A和B的差集操作:
// 差集.png // 子集:验证一个给定集合是否是另一个集合的子集
// 最后一个集合操作是子集。子集的数学概念,集合A是B的子集(或集合B包含
// 了A) ,表示为A⊆B,定义如下:
// ∀x { x ∈ A → x ∈ B }
// 意思是集合A中的每一个x(元素) ,也需要存在于B中。下图展示了集合A是集合B的子集:
// 子集.png
class Set {
private items: Object = {};
/**
* 向集合添加一个新的项
* @param value
*/
public add(value) {
if (!this.has(value)) {
this.items[value] = value;
return true;
}
}
/**
* 从集合移除一个值
* @param value
*/
public remove(value) {
if (this.has(value)) {
delete this.items[value];
return true;
}
return false;
}
/**
* 如果值在集合中,返回true,否则返回false
* @param value
*/
public has(value) {
return this.items.hasOwnProperty(value);
}
/**
* 移除集合中的所有项
*/
public clear() {
this.items = {};
}
/**
* 返回集合所包含元素的数量。与数组的length属性类似
*/
public size() {
var count = ;
for (var prop in this.items) { //{5}
if (this.items.hasOwnProperty(prop)) //{6}
++count; //{7}
}
return count;
}
/**
* 返回一个包含集合中所有值的数组
*/
public values() {
var keys = [];
for (var key in this.items) { //{7}
keys.push(key); //{8}
}
return keys;
}
public union(otherSet: Set): Set {
let unionSet = new Set();
let values = this.values();
for (let i = ; i < values.length; i++) {
unionSet.add(values[i]);
}
values = otherSet.values();
for (let i = ; i < values.length; i++) {
unionSet.add(values[i]);
}
return unionSet;
}
public intersection(otherSet: Set) {
let intersectionSet = new Set();
let values = this.values();
for (let i = ; i < values.length; i++) {
if (otherSet.has(values[i])) {
intersectionSet.add(values[i]);
}
}
return intersectionSet;
}
public difference(otherSet: Set) {
let differenceSet = new Set();
let values = this.values();
for (let i = ; i < values.length; i++) {
if (!otherSet.has(values[i])) {
differenceSet.add(values[i]);
}
}
return differenceSet;
}
public subset(otherSet: Set) {
if (this.size() > otherSet.size()) {
return false;
} else {
let values = this.values();
for (let i = ; i < values.length; i++) {
if (!otherSet.has(values[i])) {
return false;
}
}
return true;
}
}
}
// 使用 Set 类
let set = new Set(); set.add();
console.log(set.values()); //输出["1"]
console.log(set.has()); //输出true
console.log(set.size()); //输出1 set.add();
console.log(set.values()); //输出["1", "2"]
console.log(set.has()); //true
console.log(set.size()); //2 set.remove();
console.log(set.values()); //输出["2"] set.remove();
console.log(set.values()); //输出[] // 测试一下并集的代码:
var setA = new Set();
setA.add();
setA.add();
setA.add(); var setB = new Set();
setB.add();
setB.add();
setB.add();
setB.add(); var unionAB = setA.union(setB);
console.log(unionAB.values()); // 测试一下交集的代码
var setA = new Set();
setA.add();
setA.add();
setA.add(); var setB = new Set();
setB.add();
setB.add();
setB.add(); var intersectionAB = setA.intersection(setB);
console.log(intersectionAB.values());
//输出为["2", "3"],因为2和3同时存在于两个集合中 // 测试一下差集的代码
var setA = new Set();
setA.add();
setA.add();
setA.add(); var setB = new Set();
setB.add();
setB.add();
setB.add(); var differenceAB = setA.difference(setB);
console.log(differenceAB.values());
//输出为["1"],因为1是唯一一个仅存在于setA的元素。 // 测试一下子集的代码
var setA = new Set();
setA.add();
setA.add(); var setB = new Set();
setB.add();
setB.add();
setB.add(); var setC = new Set();
setC.add();
setC.add();
setC.add(); console.log(setA.subset(setB));
console.log(setA.subset(setC));
// 我们有三个集合:setA是setB的子集 (因此输出为true) , 然而setA不是setC的子集 (setC
// 只包含了setA中的2,而不包含1) ,因此输出为false
使用 Set 类
总结:我们将从头实现一个与ECMAScript 6中定义的类似的Set类。我们还介绍了在其他编程语言的集合数据结构的实现中不常见的一些方法,比如并集、交集、差集和子集。因此,相比于其他编程语言目前的Set实现,我们实现了一个非常完备的Set类
var Set = (function () {
function Set() {
this.items = {};
}
/**
* 向集合添加一个新的项
* @param value
*/
Set.prototype.add = function (value) {
if (!this.has(value)) {
this.items[value] = value;
return true;
}
};
/**
* 从集合移除一个值
* @param value
*/
Set.prototype.remove = function (value) {
if (this.has(value)) {
delete this.items[value];
return true;
}
return false;
};
/**
* 如果值在集合中,返回true,否则返回false
* @param value
*/
Set.prototype.has = function (value) {
return this.items.hasOwnProperty(value);
};
/**
* 移除集合中的所有项
*/
Set.prototype.clear = function () {
this.items = {};
};
/**
* 返回集合所包含元素的数量。与数组的length属性类似
*/
Set.prototype.size = function () {
var count = ;
for (var prop in this.items) {
if (this.items.hasOwnProperty(prop))
++count; //{7}
}
return count;
};
/**
* 返回一个包含集合中所有值的数组
*/
Set.prototype.values = function () {
var keys = [];
for (var key in this.items) {
keys.push(key); //{8}
}
return keys;
};
Set.prototype.union = function (otherSet) {
var unionSet = new Set();
var values = this.values();
for (var i_1 = ; i_1 < values.length; i_1++) {
unionSet.add(values[i_1]);
}
values = otherSet.values();
for (var i_2 = ; i_2 < values.length; i_2++) {
unionSet.add(values[i_2]);
}
return unionSet;
};
Set.prototype.intersection = function (otherSet) {
var intersectionSet = new Set();
var values = this.values();
for (var i_3 = ; i_3 < values.length; i_3++) {
if (otherSet.has(values[i_3])) {
intersectionSet.add(values[i_3]);
}
}
return intersectionSet;
};
Set.prototype.difference = function (otherSet) {
var differenceSet = new Set();
var values = this.values();
for (var i_4 = ; i_4 < values.length; i_4++) {
if (!otherSet.has(values[i_4])) {
differenceSet.add(values[i_4]);
}
}
return differenceSet;
};
Set.prototype.subset = function (otherSet) {
if (this.size() > otherSet.size()) {
return false;
}
else {
var values = this.values();
for (var i_5 = ; i_5 < values.length; i_5++) {
if (!otherSet.has(values[i_5])) {
return false;
}
}
return true;
}
};
return Set;
}());
JavaScript数据结构与算法(八) 集合(ECMAScript 6中定义的类似的Set类)的更多相关文章
- JavaScript 数据结构与算法之美 - 非线性表中的树、堆是干嘛用的 ?其数据结构是怎样的 ?
1. 前言 想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手. 非线性表(树.堆),可以说是前端程序员的内功,要知其然,知其所以然. 笔者写的 JavaScript 数据结构与算法 ...
- javascript数据结构与算法-- 二叉树
javascript数据结构与算法-- 二叉树 树是计算机科学中经常用到的一种数据结构.树是一种非线性的数据结构,以分成的方式存储数据,树被用来存储具有层级关系的数据,比如文件系统的文件,树还被用来存 ...
- 为什么我要放弃javaScript数据结构与算法(第六章)—— 集合
前面已经学习了数组(列表).栈.队列和链表等顺序数据结构.这一章,我们要学习集合,这是一种不允许值重复的顺序数据结构. 本章可以学习到,如何添加和移除值,如何搜索值是否存在,也可以学习如何进行并集.交 ...
- JavaScript数据结构与算法-集合练习
集合的实现 function Set () { this.dataStore = []; this.add = add; this.remove = remove; this.size = size; ...
- 重读《学习JavaScript数据结构与算法-第三版》-第2章 ECMAScript与TypeScript概述
定场诗 八月中秋白露,路上行人凄凉: 小桥流水桂花香,日夜千思万想. 心中不得宁静,清早览罢文章, 十年寒苦在书房,方显才高志广. 前言 洛伊安妮·格罗纳女士所著的<学习JavaScript数据 ...
- 为什么我要放弃javaScript数据结构与算法(第一章)—— JavaScript简介
数据结构与算法一直是我算比较薄弱的地方,希望通过阅读<javaScript数据结构与算法>可以有所改变,我相信接下来的记录不单单对于我自己有帮助,也可以帮助到一些这方面的小白,接下来让我们 ...
- 重读《学习JavaScript数据结构与算法-第三版》- 第4章 栈
定场诗 金山竹影几千秋,云索高飞水自流: 万里长江飘玉带,一轮银月滚金球. 远自湖北三千里,近到江南十六州: 美景一时观不透,天缘有分画中游. 前言 本章是重读<学习JavaScript数据结构 ...
- JavaScript 数据结构与算法之美 - 线性表(数组、栈、队列、链表)
前言 基础知识就像是一座大楼的地基,它决定了我们的技术高度. 我们应该多掌握一些可移值的技术或者再过十几年应该都不会过时的技术,数据结构与算法就是其中之一. 栈.队列.链表.堆 是数据结构与算法中的基 ...
- 为什么我要放弃javaScript数据结构与算法(第十一章)—— 算法模式
本章将会学习递归.动态规划和贪心算法. 第十一章 算法模式 递归 递归是一种解决问题的方法,它解决问题的各个小部分,直到解决最初的大问题.递归通常涉及函数调用自身. 递归函数是像下面能够直接调用自身的 ...
随机推荐
- Python开发简单爬虫(二)---爬取百度百科页面数据
一.开发爬虫的步骤 1.确定目标抓取策略: 打开目标页面,通过右键审查元素确定网页的url格式.数据格式.和网页编码形式. ①先看url的格式, F12观察一下链接的形式;② 再看目标文本信息的标签格 ...
- MySQL之数据的insert-delete-update操作
主要是对数据的一些基本操作:增加.删除.修改
- 需求分析&原型改进
需求&原型改进 一.给目标用户展现原型,与目标用户进一步沟通理解需求. 1.用户痛点:需要随时随地练习四则运算,并能看到用户的统计数据. 2.用户反馈:较好地解决练习需求,若能加入班级概念则更 ...
- C程序第一次作业
1-1 计算两数的和与差 1 设计思路 (1)主要描述题目算法 第一步:利用指针psum接收sum的地址,指针pdiff接收diff的地址,因此 * psum为sum, * pdiff为diff. 第 ...
- java实现同步的两种方式
同步是多线程中的重要概念.同步的使用可以保证在多线程运行的环境中,程序不会产生设计之外的错误结果.同步的实现方式有两种,同步方法和同步块,这两种方式都要用到synchronized关键字. 给一个方法 ...
- 超绚丽CSS3多色彩发光立方体旋转动画
CSS3添加了几个动画效果的属性,通过设置这些属性,可以做出一些简单的动画效果而不需要再去借助JavaScript.css3动画的属性主要分为三类:transform.transition以及anim ...
- 再议Python协程——从yield到asyncio
协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...
- 前端面试题:JS中的let和var的区别
最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别.我简单总结一下,以便各位以后面试中使用. ES6 新增了let命令,用来声明局部 ...
- 再一次, 不要使用(include/require)_once
本文地址: http://www.laruence.com/2012/09/12/2765.html 最近关于apc.include_once_override的去留, 我们做了几次讨论, 这个APC ...
- python 编码规范整理
PEP8 Python 编码规范 一 代码编排1 缩进.4个空格的缩进(编辑器都可以完成此功能),不要使用Tap,更不能混合使用Tap和空格.2 每行最大长度79,换行可以使用反斜杠,最好使用圆括号. ...