首页 > 其他分享 >数据结构之Set | 让我们一块来学习数据结构

数据结构之Set | 让我们一块来学习数据结构

时间:2023-04-04 17:02:38浏览次数:29  
标签:Set 学习 item add set values 集合 数据结构

数组(列表)、栈、队列和链表这些顺序数据结构对你来说应该不陌生了。现在我们要学习集合,这是一种不允许值重复的顺序数据结构。我们将要学到如何创建集合这种数据结构,如何添加和移除值,如何搜索值是否存在。你也会学到如何进行并集、交集、差集等数学运算。

本章内容包括:

  • 从头创建一个 Set 类
  • 用 Set 来进行数学运算

构建数据集合

集合是由一组无序且唯一(即不能重复)的项组成的。该数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中。

在深入学习集合的计算机科学实现之前,我们先看看它的数学概念。在数学中,集合是一组不同对象的集。

比如说,一个由大于或等于 0 的整数组成的自然数集合:N = {0, 1, 2, 3, 4, 5, 6, …}。集合中的对象列表用花括号({})包围。

还有一个概念叫空集。空集就是不包含任何元素的集合。比如 24 和 29 之间的素数集合,由于 24 和 29 之间没有素数(除了 1 和自身,没有其他正因数的、大于 1 的自然数),这个集合就是空集。空集用{ }表示。

你也可以把集合想象成一个既没有重复元素,也没有顺序概念的数组。在数学中,集合也有并集、交集、差集等基本运算。本文也会介绍这些运算。

创建集合类

创建基础类

用下面的 Set 类以及它的构造函数声明作为开始。

class Set {
    constructor() {
        this.items = {};
    }
}

有一个非常重要的细节是,我们使用对象而不是数组来表示集合(items)。不过,也可以用数组实现。此处用对象来实现,和我们在第 4 章与第 5 章中学习到的对象实现方式很相似。同样地,JavaScript 的对象不允许一个键指向两个不同的属性,也保证了集合里的元素都是唯一的。

接下来,需要声明一些集合可用的方法(我们会尝试模拟与 ECMAScript 2015 实现相同的Set 类)。

  • add(element):向集合添加一个新元素。
  • delete(element):从集合移除一个元素。
  • has(element):如果元素在集合中,返回 true,否则返回 false。
  • clear():移除集合中的所有元素。
  • size():返回集合所包含元素的数量。它与数组的 length 属性类似。
  • values():返回一个包含集合中所有值(元素)的数组。

has(item)方法

首先要实现的是 has(element)方法,因为它会被 adddelete 等其他方法调用。它用来检验某个元素是否存在于集合中,下面看看它的实现。

has(item) {
    return Object.prototype.hasOwnProperty.call(this.items, item);
}

除了使用Object.prototype.hasOwnProperty方法实现之外,还可以使用item in this.itemsthis.items.hasOwnProperty(item)来实现has方法。

add(item)方法

接下来要实现 add(item) 方法。

add(item) {
    if (this.has(item)) {
        return false;
    }
    this.items[item] = item;
    return true;
}

对于给定的 item,可以检查它是否存在于集合中。如果不存在,就把 item 添加到集合中,并返回 true,表示添加了该元素。如果集合中已经有了这个元素,就返回 false,表示没有添加它。

delete(item) 和 clear() 方法

下面要实现 delete(item) 方法。

delete(item) {
    if (this.has(item)) {
        delete this.items[item];
        return true
    }
    return false
}

在 delete 方法中,我们会验证给定的 item 是否存在于集合中。如果存在,就从集合中移除 item,返回 true,表示元素被移除;否则返回 false。

由于我们是使用对象来存储集合的items对象,那么就可以简单的使用对象的delete运算符从items中删除元素。

如果想移除集合中的所有值,可以用 clear 方法。

clear() {
    this.items = {}
}

size() 方法

实现size方法有几种方式:

  1. 使用一个 length 变量,每当使用 add 或 delete 方法时就控制它
  2. Object.keys(this.items).length
  3. 使用for in (要记得使用hasOwnProperty判断一下)
  4. ...

现在我们使用第2中方式来实现,代码如下

size() {
    return Object.keys(this.items).length;
}

values() 方法

要实现 values() 方法,我们同样可以使用 Object 类内置的 values 方法。

values() {
    return Object.values(values); 
}

Object.values()方法返回了一个包含给定对象所有属性值的数组。它是在ECMAScript 2017 中被添加进来的,目前只在现代浏览器中可用。

使用Set类

现在数据结构已经完成了,看看如何使用它吧。试着执行一些命令,测试我们的 Set 类。

const set = new Set(); 
set.add(1); 
console.log(set.values()); // 输出[1] 
console.log(set.has(1)); // 输出 true 
console.log(set.size()); // 输出 1 
set.add(2); 
console.log(set.values()); // 输出[1, 2] 
console.log(set.has(2)); // 输出 true 
console.log(set.size()); // 输出 2 
set.delete(1); 
console.log(set.values()); // 输出[2] 
set.delete(2); 
console.log(set.values()); // 输出[]

集合运算

集合是数学中基础的概念,在计算机领域也非常重要。它在计算机科学中的主要应用之一是数据库,而数据库是大多数应用程序的根基。集合被用于查询的设计和处理。当我们创建一条从关系型数据库(Oracle、Microsoft SQL Server、MySQL 等)中获取一个数据集合的查询语句时,使用的就是集合运算,并且数据库也会返回一个数据集合。当我们创建一条 SQL 查询命令时,可以指定是从表中获取全部数据还是获取其中的子集;也可以获取两张表共有的数据、只存在于一张表中的数据(不存在于另一张表中),或是存在于两张表内的数据(通过其他运算)。这些 SQL 领域的运算叫作联接,而 SQL 联接的基础就是集合运算。

我们可以对集合进行如下运算。

  • 并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。
  • 交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。
  • 差集:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
  • 子集:验证一个给定集合是否是另一集合的子集。

重要的是要注意,本文实现的 unionintersectiondifference 方法不会修改当前的 Set 类实例或是作为参数传入的 otherSet。没有副作用的方法和函数被称为纯函数。纯函数不会修改当前的实例或参数,只会生成一个新的结果。这在函数式编程中是非常重要的概念。

并集

并集的数学概念。集合 A 和集合 B 的并集表示为 \(A ∪ B\),定义如下。

\[A ∪ B = { x ∣ x ∈ A ∨ x ∈ B } \]

意思是 x(元素)存在于 A 中,或 x 存在于 B 中。下图展示了并集运算。

数据结构之Set | 让我们一块来学习数据结构_数组

代码实现

union(otherSet) {
    let unionSet = new Set();
    let values = this.values();
    values.forEach((value) => {
        unionSet.add(value);
    });
    values = otherSet.values();
    values.forEach((value) => {
        unionSet.add(value);
    });
    return unionSet;
}

交集

交集的数学概念。集合 A 和集合 B 的交集表示为 \(A ∩ B\),定义如下。

\[A ∩ B = { x ∣ x ∈ A ∧ x ∈ B } \]

意思是 x(元素)存在于 A 中,且 x 存在于 B 中。下图展示了交集运算。

数据结构之Set | 让我们一块来学习数据结构_Set_02

代码实现

intersection(otherSet) {
    let intersectionSet = new Set();
    const values = this.values();
    const otherValues = otherSet.values();
    let smallerValues = values;
    let biggerValues = otherValues;
    if (otherValues.length < values.length) {
        smallerValues = otherValues;
        biggerValues = values;
    }
    smallerValues.forEach((value) => {
        if (biggerValues.includes(value)) {
            intersectionSet.add(value);
        }
    });
    return intersectionSet;
}

> 为了减少循环次数,在代码中判断了哪个集合的长度最小,然后循环长度较小的集合,以达到减少循环次数的目的。

差集

差集的数学概念。集合 A 和集合 B 的差集表示为 \(A - B\),定义如下。

\[A ∪ B = { x ∣ x ∈ A ∧ x ∉ B } \]

意思是 x(元素)存在于 A 中,且 x 不存在于 B 中。下图展示了集合 A 和集合 B 的差集运算。

数据结构之Set | 让我们一块来学习数据结构_JavaScript_03

代码实现

difference(otherSet) {
    let differenceSet = new Set();

    this.values().forEach((value) => {
        if (!otherSet.has(value)) {
            differenceSet.add(value);
        }
    });
    return differenceSet;
}

子集

要介绍的最后一个集合运算是子集。其数学概念的一个例子是集合 A 是集合 B 的子集(或集合 B 包含集合 A),表示为 \(A ∈ B\),定义如下。

\[A ∪ B = { x ∣ ∀x ∈ A =&gt; x ∈ B } \]

意思是集合 A 中的每一个 x(元素),也需要存在于集合 B 中。下图展示了集合 A 是集合 B 的子集。

数据结构之Set | 让我们一块来学习数据结构_JavaScript_04

代码实现

isSubsetOf(otherSet) {
    if (this.size() > otherSet.size()) {
        return false;
    }
    let isSubset = true;
    const values = this.values();
    const size = this.size();
    for (let i = 0; i < size; i++) {
        if (!otherSet.has(values[i])) {
            isSubset = false;
            break;
        }
    }
    return isSubset;
}

参考资料

  • 学习JavaScript数据结构与算法第三版


标签:Set,学习,item,add,set,values,集合,数据结构
From: https://blog.51cto.com/jikun/6169050

相关文章

  • js中e.clientX e.pageX e.offsetX e.screenX之间的区别
     event.clientX、event.clientY鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条。IE事件和标准事件都定义了这2个属性event.pageX、event.pageY类似于event.clientX、event.clientY,但它们使用的是文档坐标而非窗口坐标。这2个属性不是标准属性,但......
  • 小皮1-click漏洞的代码审计学习笔记
    漏洞简介漏洞起源于前段时间比较火的小皮1-click漏洞,用户名登录处缺少过滤,导致可以直接构造恶意payload实现存储型XSS,结合小皮本身所具有的计划任务,XSS+CSRF实现了RCE。因为用户名登录处缺少过滤,所以可以尝试SQL漏洞。环境搭建windows上实际操作了一下,不方便进......
  • 基于mnist手写数字数据库的深度学习网络训练和数字识别matlab仿真
    1.算法描述        MNIST数据集(MixedNationalInstituteofStandardsandTechnologydatabase)是美国国家标准与技术研究院收集整理的大型手写数字数据库,该数据集包含60000 个于训练的样本和10000 个于测试的样本,图像是固定⼤小(28x28像素),每个像素的值为......
  • mysql中find_in_set()函数的使用
    首先举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有1头条、2推荐、3热点、4图文等等。现在有篇文章他既是头条,又是热点,还是图文,type中以1,3,4的格式存储。那我们如何用sql查找所有type中有4的图文类型的文章呢?? 这就要我们的find_in_set出马的时候到了。......
  • Markdown学习
    #+空格Markdown学习##+空格二级标题###+空格三级标题  字体hello,worldhello,worldhello,worldhello,world 引用大于号+空格分割线三个-三个*图片!+[截图]+()本地地址或网络地址超链接点击跳转[]+()列表数字+.-+空格表格      ......
  • 4.4学习总结(虚拟试衣算法初步框架构思)
    昨天上台演示了项目框架并且讲述了未来对项目规划的构思,我们组是最后一组,整体等待过程还是很煎熬的比我们队优秀的作品有很多,所以还是很有压力的不过我们会尽力在接下来的时间内,争取完成所介绍的所有功能......
  • 深入学习和理解 Redux
    vivo互联网技术微信公众号 作者:曾超Redux官网上是这样描述Redux,ReduxisapredictablestatecontainerforJavaScriptapps.(Redux是JavaScript状态容器,提供可预测性的状态管理)。 目前ReduxGitHub有5w多star,足以说明Redux受欢迎的程度。一、WhyRedux在说为什么用Redux......
  • 【软考】信息系统项目管理师,考试大纲与历年考点分析,学习方法(2021版)
    序信息系统项目管理师,考试大纲与历年考点分析,学习方法(2021版)1、顺序因为内容量,考试大纲>历年考点>学习方法但是使用频率却是,学习方法>历年考点>考试大纲所以本文放置的顺序倒了一下,按照频率摆放章节。2、说明本文仅供个人学习备考期间使用,数据来源是江山老师的2021年已经考......
  • Chisel3 使用 DPI-C,发现在 Chisel 环境下 printf 没问题,但是 set_pc 死活传不到 cpp
    大概率是因为你使用了SignExt之类的封装这类封装只会把”值“传给DPI-C,而不会把线连给DPIC,即,传过去的是调用set_pc时的值,而不是引用这样会造成CPP获取不了相应线路的指针 如下图     这些也是错的......
  • Unity升级后打包AssetBundle变慢
    1)Unity升级后打包AssetBundle变慢​2)打包使有些资源合成了一个资源data.unity3d,有些分开的原因3)Unreal在移动设备中无法使用Stat命令获取到GPUThread的耗时4)Unity中如何看到相机视野范围内的剔除结果这是第330篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社......