一、什么是集合##

集合就是不同对象的无序聚集。那么链表和集合有什么关系呢?我们来变个魔术。如下图是各种颜色组成的链表:

下面我们一步步把链表变成集合。

第一步砍去链接

第二步去掉重复

第三步放到一个框里摇一摇就成集合了

可以看出集合有这些特点:

  • 无序:链表去掉链接,就是去掉元素间有序状态。
  • 不重复:去掉重复的玫红色。

    虽然说集合是一种数学概念,但在实际生活中无处不透露着集合。比如一个班级的学生是一个集合。班级里的男生又是一个集合。

二、集合的结构##

大卫哥这里为了简化概念的描述,继续用单链表来表示集合,但是在对集合做计算的时候单链表并不合适,数据量大的时候它的弊端就会显现,在讲到后面的数据结构和算法的时候,我们再回头来完善前面讲的数据接口的实现。

三、接口说明及实现##

1、Init###

初始化集合,本质是初始化链表。

func (set *Set) Init(match ...MatchFun) {
lst := new(List)
(*set).list = lst if len(match) == 0 {
lst.Init()
} else {
lst.Init(match[0])
}
}

要比较集合中的元素,我们得传入一个比较函数,这里的match是我们的自定义类型MatchFun,大家可以查看代码里的定义。

2、Insert###

把元素放入集合中。

func (set *Set) Insert(data Object) bool {
if (!set.IsMember(data)) {
return (*set).list.Append(data)
} return false
}

3、IsEmpty###

是否是空集合。

func (set *Set) IsMember(data Object) bool {
return (*set).list.IsMember(data);
}

4、IsMember###

是否是集合元素。

func (set *Set) IsMember(data Object) bool {
return (*set).list.IsMember(data);
}

5、Remove###

删除指定集合元素。

func (set *Set) Remove(data Object) bool {
return (*set).list.Remove(data)
}

6、Union###

并集计算。

func (set *Set) Union(set1 *Set) *Set {
if (set1 == nil) {
return nil
}
nSet := new(Set)
nSet.Init((*((*set).list)).myMatch) if (set.IsEmpty() && set1.IsEmpty()) {
return nSet
} for i := uint64(0); i < set.getSize(); i++ {
nSet.Insert(set.getAt(i))
} var data Object
for i := uint64(0); i < set1.getSize(); i++ {
data = set1.getAt(i)
if (!nSet.IsMember(data)) {
nSet.Insert(data)
}
} return nSet
}

计算set和set1的并集。

7、InterSection###

计算交集。

func (set *Set) InterSection(set1 *Set) *Set {
if (set1 == nil) {
return nil
}
nSet := new(Set)
nSet.Init((*((*set).list)).myMatch) if (set.IsEmpty() || set1.IsEmpty()) {
return nSet
} fSet := set
sSet := set1
lenth := set.getSize() if (set1.getSize() < lenth) {
fSet = set1
sSet = set
} var data Object
for i := uint64(0) ; i < lenth; i++ {
data = fSet.getAt(i)
if (sSet.IsMember(data)) {
nSet.Insert(data)
}
}
return nSet
}

8、Difference###

计算差集。

func (set *Set) Difference(set1 *Set) *Set {
if (set1 == nil) {
return nil
} nSet := new(Set)
nSet.Init((*((*set).list)).myMatch)
if (set.IsEmpty()) {
return nSet
} var data Object
for i := uint64(0); i < set.getSize(); i++ {
data = set.getAt(i) if (!set1.IsMember(data)) {
nSet.Insert(data)
}
} return nSet
}

返回的集合是属于set,但不属于set1的集合。

9、IsSubSet###

    func (set *Set) IsSubSet(subSet *Set) bool {
if (set == nil) {
return false
} if (subSet == nil) {
return true
} for i := uint64(0); i < subSet.getSize(); i++ {
if (!(set.IsMember(subSet.getAt(i)))) {
return false
}
} return true
}

确认subSet是否是set的子集。

10、Equals###

    func (set *Set) Equals(set1 *Set) bool {
if (set == nil || set1 == nil) {
return false
} if (set.IsEmpty() && set1.IsEmpty()) {
return true
} nSet := set.InterSection(set1) return (set.getSize() == nSet.getSize())
}

判断set和set1中集合元素是否一样。

11、访问集合元素###

因为集合是没有顺序的,所以没法用序号来访问集合元素(虽然这里是用单链表实现)。这里我们用迭代器的方式来实现元素的访问。首先我们定义一个迭代器的接口。

(1) Iterator####

    type Iterator interface{
HasNext() bool
Next() Object
}

(2) SetIterator####

    type SetIterator struct {
index uint64
set *Set
}

因为Iterator是接口,没法保存状态,所以我们得定义一个类型来保存每次访问的游标。这里的游标是序号。

(3) GetIterator####

返回一个实现了Iterator接口的对象。

    func (set *Set) GetIterator() *SetIterator {
iterator := new(SetIterator)
(*iterator).index = 0
(*iterator).set = set return iterator
}

(4) HasNext####

是否有其他元素没访问到?

    func (iterator *SetIterator) HasNext() bool {
set := (*iterator).set
index := (*iterator).index return (index < set.getSize())
}

这是Iterator中HasNext方法的实现。

(5) Next####

获取其他元素。

    func (iterator *SetIterator) Next() Object {
set := (*iterator).set
index := (*iterator).index if (index < set.getSize()) {
data := set.getAt(index)
(*iterator).index++ return data
} return nil
}

四、小结##

集合在概率中有很多应用,这里我们仅仅是用单链表简单的实现了集合,在大量数据下,计算效率很低。随着学习的深入,我们会优化这些数据接口的实现。

代码下载

第六节 Go数据结构之集合的更多相关文章

  1. ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借

    ASP.NET MVC深入浅出系列(持续更新)   一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...

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

    前言 总括: 本文讲解了数据结构中的[集合]概念,并使用javascript实现了集合. 原文博客地址:学习javascript数据结构(三)--集合 知乎专栏&&简书专题:前端进击者 ...

  3. java 16 - 5 LinkedList模拟栈数据结构的集合

    请用LinkedList模拟栈数据结构的集合,并测试 题目的意思是: 你自己的定义一个集合类,在这个集合类内部可以使用LinkedList模拟. package cn_LinkedList; impo ...

  4. 第一百二十六节,JavaScript,XPath操作xml节点

    第一百二十六节,JavaScript,XPath操作xml节点 学习要点: 1.IE中的XPath 2.W3C中的XPath 3.XPath跨浏览器兼容 XPath是一种节点查找手段,对比之前使用标准 ...

  5. 第十六节、基于ORB的特征检测和特征匹配

    之前我们已经介绍了SIFT算法,以及SURF算法,但是由于计算速度较慢的原因.人们提出了使用ORB来替代SIFT和SURF.与前两者相比,ORB有更快的速度.ORB在2011年才首次发布.在前面小节中 ...

  6. 《Linux内核分析》 第六节 进程的描述和进程的创建

    <Linux内核分析> 第六节 进程的描述和进程的创建 20135307 张嘉琪 原创作品转载请注明出处 +<Linux内核分析>MOOC课程http://mooc.study ...

  7. 第二百九十六节,python操作redis缓存-Hash哈希类型,可以理解为字典类型

    第二百九十六节,python操作redis缓存-Hash哈希类型,可以理解为字典类型 Hash操作,redis中Hash在内存中的存储格式如下图: hset(name, key, value)name ...

  8. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

  9. CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第六节

    原文链接 第六节:全局内存和CUDA RPOFILER  Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在 ...

随机推荐

  1. 企业级Nginx增加日志选项

    日志介绍 目的:将用户的访问信息记录到指定的文件中由ngx_http_log_module模块负责 访问日志参数: access_log:指定日志文件的路径和使用何种日志格式记录日志 log_form ...

  2. Excel课程表

  3. windows下sqli-labs的搭建及学习(GET篇)

    环境搭建: 源码下载地址:https://github.com/Audi-1/sqli-labs 需要搭建以下环境: apache+mysql+php Tomcat+mysql+java(部分关卡需要 ...

  4. MVC过滤器的使用总结

    一.过滤器的作用 在MVC项目当中,当我们要实现这些功能时:身份验证,异常处理.日志记录,性能统计,如果按照一般的做法那就需要在每个页面重复做这些工作,这样做起来不仅费时费力,代码也会变得冗余难懂,如 ...

  5. Python3基本数据类型(二、字符串)

    Python3字符串 ①字符串比较 1.比较字符串是否相同: ==:使用==来比较两个字符串内的value值是否相同 is:比较两个字符串的id值. 2.字符串的长度比较 len():显示字符串的长度 ...

  6. P2585 [ZJOI2006]三色二叉树

    题目描述 输入输出格式 输入格式: 输入文件名:TRO.IN 输入文件仅有一行,不超过500000个字符,表示一个二叉树序列. 输出格式: 输出文件名:TRO.OUT 输出文件也只有一行,包含两个数, ...

  7. [USACO08JAN]Telephone Lines

    嘟嘟嘟 题意概括一下,就是在无向图上求一条1到n的路径,使路径上第k + 1大的边权尽量小. 考虑dp,令dp[i][j] 表示走到节点 i,路线上有 j 条电话线免费时,路径上最贵的电缆花费最小是多 ...

  8. TensorFlow函数(三)tf.variable_scope() 和 tf.name_scope()

    tf.name_scope() 此函数作用是共享变量.在一个作用域scope内共享一些变量,简单来说,就是给变量名前面加个变量空间名,只限于tf.Variable()的变量 tf.variable_s ...

  9. 一款不错的网站压力测试工具webbench

    webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: 引用 wget htt ...

  10. druid相关资料

    官方资料直达地址: Druid 首页 https://github.com/alibaba/druid/wiki/%E9%A6%96%E9%A1%B5 Druid 常见问题 https://githu ...