经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Go语言 » 查看文章
第六节 Go数据结构之集合
来源:cnblogs  作者:懒人记  时间:2018/9/25 20:30:10  对本文有异议

一、什么是集合

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

下面我们一步步把链表变成集合。
第一步砍去链接

第二步去掉重复

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

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

  • 无序:链表去掉链接,就是去掉元素间有序状态。
  • 不重复:去掉重复的玫红色。
    虽然说集合是一种数学概念,但在实际生活中无处不透露着集合。比如一个班级的学生是一个集合。班级里的男生又是一个集合。

二、集合的结构

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

三、接口说明及实现

1、Init

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

  1. func (set *Set) Init(match ...MatchFun) {
  2. lst := new(List)
  3. (*set).list = lst
  4. if len(match) == 0 {
  5. lst.Init()
  6. } else {
  7. lst.Init(match[0])
  8. }
  9. }

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

2、Insert

把元素放入集合中。

  1. func (set *Set) Insert(data Object) bool {
  2. if (!set.IsMember(data)) {
  3. return (*set).list.Append(data)
  4. }
  5. return false
  6. }

3、IsEmpty

是否是空集合。

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

4、IsMember

是否是集合元素。

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

5、Remove

删除指定集合元素。

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

6、Union

并集计算。

  1. func (set *Set) Union(set1 *Set) *Set {
  2. if (set1 == nil) {
  3. return nil
  4. }
  5. nSet := new(Set)
  6. nSet.Init((*((*set).list)).myMatch)
  7. if (set.IsEmpty() && set1.IsEmpty()) {
  8. return nSet
  9. }
  10. for i := uint64(0); i < set.getSize(); i++ {
  11. nSet.Insert(set.getAt(i))
  12. }
  13. var data Object
  14. for i := uint64(0); i < set1.getSize(); i++ {
  15. data = set1.getAt(i)
  16. if (!nSet.IsMember(data)) {
  17. nSet.Insert(data)
  18. }
  19. }
  20. return nSet
  21. }

计算set和set1的并集。

7、InterSection

计算交集。

  1. func (set *Set) InterSection(set1 *Set) *Set {
  2. if (set1 == nil) {
  3. return nil
  4. }
  5. nSet := new(Set)
  6. nSet.Init((*((*set).list)).myMatch)
  7. if (set.IsEmpty() || set1.IsEmpty()) {
  8. return nSet
  9. }
  10. fSet := set
  11. sSet := set1
  12. lenth := set.getSize()
  13. if (set1.getSize() < lenth) {
  14. fSet = set1
  15. sSet = set
  16. }
  17. var data Object
  18. for i := uint64(0) ; i < lenth; i++ {
  19. data = fSet.getAt(i)
  20. if (sSet.IsMember(data)) {
  21. nSet.Insert(data)
  22. }
  23. }
  24. return nSet
  25. }

8、Difference

计算差集。

  1. func (set *Set) Difference(set1 *Set) *Set {
  2. if (set1 == nil) {
  3. return nil
  4. }
  5. nSet := new(Set)
  6. nSet.Init((*((*set).list)).myMatch)
  7. if (set.IsEmpty()) {
  8. return nSet
  9. }
  10. var data Object
  11. for i := uint64(0); i < set.getSize(); i++ {
  12. data = set.getAt(i)
  13. if (!set1.IsMember(data)) {
  14. nSet.Insert(data)
  15. }
  16. }
  17. return nSet
  18. }

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

9、IsSubSet

  1. func (set *Set) IsSubSet(subSet *Set) bool {
  2. if (set == nil) {
  3. return false
  4. }
  5. if (subSet == nil) {
  6. return true
  7. }
  8. for i := uint64(0); i < subSet.getSize(); i++ {
  9. if (!(set.IsMember(subSet.getAt(i)))) {
  10. return false
  11. }
  12. }
  13. return true
  14. }

确认subSet是否是set的子集。

10、Equals

  1. func (set *Set) Equals(set1 *Set) bool {
  2. if (set == nil || set1 == nil) {
  3. return false
  4. }
  5. if (set.IsEmpty() && set1.IsEmpty()) {
  6. return true
  7. }
  8. nSet := set.InterSection(set1)
  9. return (set.getSize() == nSet.getSize())
  10. }

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

11、访问集合元素

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

(1) Iterator

  1. type Iterator interface{
  2. HasNext() bool
  3. Next() Object
  4. }

(2) SetIterator

  1. type SetIterator struct {
  2. index uint64
  3. set *Set
  4. }

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

(3) GetIterator

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

  1. func (set *Set) GetIterator() *SetIterator {
  2. iterator := new(SetIterator)
  3. (*iterator).index = 0
  4. (*iterator).set = set
  5. return iterator
  6. }

(4) HasNext

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

  1. func (iterator *SetIterator) HasNext() bool {
  2. set := (*iterator).set
  3. index := (*iterator).index
  4. return (index < set.getSize())
  5. }

这是Iterator中HasNext方法的实现。

(5) Next

获取其他元素。

  1. func (iterator *SetIterator) Next() Object {
  2. set := (*iterator).set
  3. index := (*iterator).index
  4. if (index < set.getSize()) {
  5. data := set.getAt(index)
  6. (*iterator).index++
  7. return data
  8. }
  9. return nil
  10. }

四、小结

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号