集合是一种不允许值重复的顺序数据结构。
本文将详解集合的实现思路并使用TypeScript实现类似于ES6中的Set集合以及集合的基本运算,欢迎各位感兴趣的开发者阅读本文。
集合有一个很重要的特点:它的内部元素不会重复,因此我们可以使用JavaScript中对象来描述结合。
一个较为完善的集合类必须具备:判断元素是否在集合中、向集合中添加元素、删除集合中的元素等基础函数,接下来我们来分析下这些函数的实现思路。
集合是数学中基础的概念,在计算机领域也非常重要。接下来我们来看看集合相关运算的实现思路,实现之前我们先用图解的形式描述下常用的几个集合运算。
我们捋清实现思路后,接下来我们将上述实现思路转换为代码:
export default class Set<T>{
}
interface setItemsType<T> {
[propName: string]: T;
}
private items: setItemsType<T>;
constructor() {
this.items = {};
}
has(element: any){
// Object原型有hasOwnProperty方法用于判断对象是否有特定属性
return Object.prototype.hasOwnProperty.call(this.items,element);
}
add(element: any){
if(!this.has(element)){
this.items[element] = element;
return true;
}
return false;
}
delete(element: any){
if(this.has(element)){
delete this.items[element];
return true;
}
return false;
}
clear(){
this.items = {};
}
size(){
let count = 0;
for (let key in this.items){
if(this.items.hasOwnProperty(key)){
count++;
}
}
return count;
}
values(){
let values = [];
for (let key in this.items){
if(this.items.hasOwnProperty(key)){
values.push(key);
}
}
return values;
}
union(otherSet: Set<T>){
// 声明并集变量
const unionSet = new Set();
this.values().forEach(value => unionSet.add(value));
otherSet.values().forEach(value => unionSet.add(value));
return unionSet;
}
intersection(otherSet: Set<T>) {
// 声明交集变量
const intersectionSet = new Set();
// 获取当前实例集合中的元素
const values = this.values();
// 获取另一个集合中的元素
const otherValues = otherSet.values();
// 假设当前实例集合中的元素最多
let biggerSet = values;
// 假设另一个元素集合中的元素最少
let smallerSet = otherValues;
// 如果另一个集合中的元素个数比当前元素集合中的个数多,则交换变量
if(otherValues.length - values.length > 0){
biggerSet = otherValues;
smallerSet = values;
}
// 遍历元素最少的集合数组,节约性能开销
smallerSet.forEach(value => {
if (biggerSet.includes(value)){
intersectionSet.add(value);
}
});
// 返回交集集合
return intersectionSet;
}
difference(otherSet: Set<T>) {
// 声明差集变量
const differenceSet = new Set();
// 遍历当前实例中的集合
this.values().forEach(value => {
// 如果当前遍历到元素不存在与另一个集合中,则将档当前元素添加进差集变量里
if(!otherSet.has(value)){
differenceSet.add(value);
}
});
// 返回差集变量
return differenceSet;
} isSubsetOf(otherSet: Set<T>) {
if(this.size() > otherSet.size()){
return false;
}
let isSubset = true;
this.values().every(value => {
if(!otherSet.has(value)){
isSubset = false;
return false;
}
return true;
});
return isSubset;
}
isSubsetOf(otherSet: Set<T>) {
if(this.size() > otherSet.size()){
return false;
}
let isSubset = true;
this.values().every(value => {
if(!otherSet.has(value)){
isSubset = false;
return false;
}
return true;
});
return isSubset;
}
完整代码请移步:Set.ts
接下来,我们对上述实现的Set类进行测试,确保每个函数都正常工作。
const set = new Set();
set.add(11);
set.add(12);
set.add(13);
set.delete(11);
console.log(set.size())
console.log("获取集合中的元素",set.values());
set.clear();
console.log("获取集合大小",set.size());
// 集合运算
const A = new Set();
A.add(10);
A.add(11);
A.add(12);
A.add(13);
A.add(1);
A.add(2);
const B = new Set();
B.add(1);
B.add(2);
B.add(3);
// 求A和B的并集
console.log("A和B的并集",A.union(B).values());
// 求A和B的交集
console.log("A和B的交集",A.intersection(B).values());
//求A和B的差集
console.log("A和B的差集",A.difference(B).values());
// 求C是否为D的子集
const C = new Set();
C.add(1);
C.add(2);
C.add(3);
C.add(4);
C.add(5);
const D = new Set();
D.add(1);
D.add(2);
D.add(3);
D.add(9)
console.log(D.isSubsetOf(C));
完整代码请移步:SetTest.js
阅读量:2011
点赞量:0
收藏量:0