数据结构和算法(六)之集合结构

数据结构和算法(六)之集合结构

几乎每种编程语言中,都有集合结构

集合比较常见的实现方式是哈希表,我们这里来实现一个封装的集合类

一. 集合介绍

集合的特点

  • 集合通常是由一组无序的,不能重复的元素构成
    • 和数字的集合名词比较相似,但是数学中的集合范围更大一些,也允许集合中的元素重复。
    • 在计算机中,集合通常表示的结构中元素时不允许重复的。
  • 看成一种特殊的数组
    • 其实集合可以将它看成一种特殊的数组
    • 特殊之处在于里面的元素没有顺序,也不能重复。
    • 没有顺序意味着不能通过下标值进行访问,不能重复意味着相同的对象在集合中只会存在一份。

集合的实现

  • 我们要像之前学习其他数据结构一样,来学习一下集合
  • 最主要的学习方法就是封装一个属于自己的集合类,并且可以通过该类进行集合相关的操作。
    • 2011年6月份发布的 ES5 中已经包含 Array
    • 2015年6月份发布的 ES6 中已经包含了Set类,所以其实我们可以不封装,直接使用它。

二. 封装集合

创建集合类

  • 我们先来封装一个Set

    // 封装集合的构造函数
    function Set() {
    	// 使用一个对象来保存集合的元素
        this.items = {}
        
    }
    
  • 代码解析:

    • 代码就是封装了一个集合的构造函数。
    • 在集合中,添加了一个items属性,用于保存之后添加到集合中的元素。因为Objectkeys本身就是一个集合。
    • 后续我们给集合添加对应的操作方法。

操作的方法

  • 集合有哪些常见的操作方法呢?

    • add(value):向集合添加一个新的项。

    • remove(value):从集合移除一个值。

    • has(value):如果值在集合中,返回true,否则返回false

    • clear():移除集合中所有项。

    • size():返回集合所包含元素的数量。与数组的length属性类似。

    • values():返回一个包含集合中所有值得数组。

    • union(otherSet) :求两个集合的并集

    • intersection(otherSet) :求两个集合的交集

    • difference(otherSet) :求两个集合的差集

    • subset(otherSet):求两个集合的子集

  • has(value)方法

    // 判断集合中是否有某个元素
    Set.prototype.has =  function (value) {
    	return this.items.hasOwnProperty(value)
    }
    
  • add(value)方法

    // 向集合中添加元素
    Set.prototype.add = function (value) {
    	// 1.判断集合中是否已经包含了该元素
    	if(this.has(value)) return false
    	
        // 2.将元素添加到集合中
        this.items[value] = value
        return true
    }
    
  • remove(value)方法

    // 从集合中删除某个元素
    Set.prototype.remove = function (value) {
    	// 1.判断集合中是否包含该元素
        if(!this.has(value)) return false
        
        // 2.包含该元素,那么将元素删除
        delete this.items[value]
        return true
    }
    
  • clear()方法

    // 清空集合中所有的元素
    Set.prototype.clear = function () {
    	this.items = {}
    }
    
  • size()方法

    // 获取集合的大小
    Set.prototype.size = function () {
    	return Object.keys(this.items).length
        /*
        考虑兼容性问题,使用下面的代码
        var count = 0
        for (var value in this.items) {
        	if(this.items.hasOwnProperty(value)){
        		count++
        	}
        }
        return count
        */
    }
    
  • values()方法

    // 获取集合中所有的值
    Set.prototype.values = function () {
    	return Object.keys(this.items)
        
        /*
        考虑兼容性问题,使用一下代码
        var keys = []
        for(var value in this.items){
        	keys.push(value)
        } 
        return keys
        */
    }
    
  • union(otherSer)方法

    // 求两个集合的并集
    Set.prototype.union = function(otherSet) {
        // 1.创建一个新歌集合
        let unionSet = new Set()
        
        // 2.将当前集合(this)的所有 value ,添加到新集合(unionSet)
        for (let value of this.values()) {
            unionSet.add(value)
        }
        
        // 3.将 otherSet 集合的所有 value,添加到新集合 (unionSet) 中
        for(let value of otherSet.values()) {
            unionSet.add(value)    // add() 已经有重复判断
            
        }
        
        return unionSet
    }
    
  • intersection(otherSet) 方法

    // 求两个集合的交集
    Set.prototype.intersection = function (otherSet) {
    	// 1.创建一个新集合
        let intersectionSet = new Set()
        
        // 2.从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在
        for(let value of this.values()) {
            if (otherSet.has(value)) {
                intersectionSet.add(value)
            }
        }
        
        return intersectionSet
    }
    
  • difference(otherSet)方法

    // 求两个集合的差集
    Set.prototype.difference = function (otherSet) {
    	// 1.创建一个新的集合
        let differenceSet = new Set()
        
        // 2.从当前集合中取出一个 value ,判断是否在 otherSet 集合中存在
        for(let value of this.values()) {
            if(!otherSet.has(value)) {
                differenceSet.add(value)
            }
        }
        
        // 3.从otherSet集合中取出一个 value,判断是否在 当前集合 中存在,不存在的即为差集
    	for (let value of otherSet.values()) {
    		if(!this.has(value)) {
    			differenceSet.add(value);
    		}
    	}
        
        return differenceSet
    }
    
  • subset(otherSet)方法

    // 求是否为子集
    Set.prototype.subset = function (otherSet) {
    	// 从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在,有不存在的返回 false
        // 遍历完所有的,返回 true
        for(let value of this.values()) {
            if(!otherSet.has(value)) {
                return false
            }
        }
        return true
    }
    

集合的使用

  • 我们来简单使用和测试一下封装的集合类

    // 测试和使用集合类
    let set = new Set()
    
    // 添加元素
    set.add(1)
    alert(set.values())  // 1
    set.add(1)
    alert(set.values())  // 1
    
    set.add(100)
    set.add(200)
    alert(set.values())  // 1,100,200
    
    // 判断是否包含元素
    alert(set.has(100))  // true
    
    // 删除元素
    set.remove(100)
    alert(set.values())  // 1,200
    
    // 获取集合的大小
    alert(set.values()) // 2
    set.clear()
    alert(set.values()) // 0
    
    // ------------集合间操作-------------//
    const setA = new Set()
    setA.add('111')
    setA.add('222')
    setA.add('333')
    alert(setA.values())   // 111,222,333
    
    const setB = new Set()
    setB.add('111')
    setB.add('222')
    setB.add('aaa')
    setB.add('bbb')
    alert(setB.values())  // 111,222,aaa,bbb
    
    // 求两个集合的并集
    alert(setA.union(setB).values()) // 111,222,333,aaa,bbb
    
    // 求两个集合的交集
    alert(setA.intersection(setB).values()) // 111,222
    
    // 求两个集合的差集
    alert(setA.difference(setB).values()) // 333,aaa,bbb
    
    // 求集合A是否是集合B的子集
    alert(setA.subset(setB))  // false
    

三. 完整代码

// 封装集合的构造函数
function Set() {
    // 使用一个对象来保存集合的元素
    this.items = {}

    // 集合的操作方法
    // 判断集合中是否有某个元素
    Set.prototype.has = function (value) {
        return this.items.hasOwnProperty(value)
    }

    // 向集合中添加元素
    Set.prototype.add = function (value) {
        // 1.判断集合中是否已经包含了该元素
        if (this.has(value)) return false

        // 2.将元素添加到集合中
        this.items[value] = value
        return true
    }

    // 从集合中删除某个元素
    Set.prototype.remove = function (value) {
        // 1.判断集合中是否包含该元素
        if (!this.has(value)) return false

        // 2.包含该元素, 那么将元素删除
        delete this.items[value]
        return true
    }

    // 清空集合中所有的元素
    Set.prototype.clear = function () {
        this.items = {}
    }

    // 获取集合的大小
    Set.prototype.size = function () {
        return Object.keys(this.items).length

        /*
        考虑兼容性问题, 使用下面的代码
        var count = 0
        for (var value in this.items) {
            if (this.items.hasOwnProperty(value)) {
                count++
            }
        }
        return count
        */
    }

    // 获取集合中所有的值
    Set.prototype.values = function () {
        return Object.keys(this.items)

        /*
        考虑兼容性问题, 使用下面的代码
        var keys = []
        for (var value in this.items) {
            keys.push(value)
        }
        return keys
        */
    }
    
    // ---------- 集合间操作 ------------- //
    // 求两个集合的并集
	Set.prototype.union = function(otherSet) {
    	// 1.创建一个新歌集合
    	let unionSet = new Set()
    
    	// 2.将当前集合(this)的所有 value ,添加到新集合(unionSet)
    	for (let value of this.values()) {
        	unionSet.add(value)
    	}
    
    	// 3.将 otherSet 集合的所有 value,添加到新集合 (unionSet) 中
    	for(let value of otherSet.values()) {
        	unionSet.add(value)    // add() 已经有重复判断
        
    	}
    
   		return unionSet
	}
    
    // 求两个集合的交集
	Set.prototype.intersection = function (otherSet) {
		// 1.创建一个新集合
    	let intersectionSet = new Set()
    
    	// 2.从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在
    	for(let value of this.values()) {
        	if (otherSet.has(value)) {
            	intersectionSet.add(value)
        	}
    	}
    
    	return intersectionSet
	}
    
    // 求两个集合的差集
	Set.prototype.difference = function (otherSet) {
		// 1.创建一个新的集合
    	let differenceSet = new Set()
    
    	// 2.从当前集合中取出一个 value ,判断是否在 otherSet 集合中存在
    	for(let value of this.values()) {
        	if(!otherSet.has(value)) {
            	differenceSet.add(value)
        	}
    	}
        
        // 3.从otherSet集合中取出一个 value,判断是否在 当前集合 中存在,不存在的即为差集
		for (let value of otherSet.values()) {
			if(!this.has(value)) {
				differenceSet.add(value);
			}
		}
        
    	return differenceSet
	}
    
    
    // 求是否为子集
	Set.prototype.subset = function (otherSet) {
		// 从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在,有不存在的返回 false
    	// 遍历完所有的,返回 true
    	for(let value of this.values()) {
        	if(!otherSet.has(value)) {
            	return false
        	}
    	}
    	return true
	}
    
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yige001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值