在数据结构之前,集合首先是个非常重要的数学概念,离散数学的第一课应该都是讲集合吧。。。
在数据结构中,集合是由一组无序且唯一的项组成的。这里对这种数据结构进行了封装,使用对象来存储项(键和值都为该项自身),提供了添加项、删除项等一系列基本的集合操作方法。并在构造器对象上定义了求两集合并集、交集、差集、笛卡尔积、环积的方法,以及判断是否为子集、真子集、同一集合的方法。 关于构造器对象上定义的这些方法,大家可以将它添加至原型对象中并进行相应修改,使得可以自动将调用对象作为方法的第一个参数。 这里还支持链式调用。 各方法功能见代码注释:
//set
function Set(){
//私有变量
var items = {},
size = 0;
//向集合中添加元素 Object(Set)
this.add = function(value){
if(!this.has(value)){
items[value] = value;
size++;
return this;
}
throw 'Set.add() false';
return false;
};
//从集合中移除元素 Object(Set)
this.remove = function(value){
if(this.has(value)){
delete items[value];
size--;
return this;
}
throw 'Set.remove() false';
return false;
};
//集合中是否存在该元素 Boolean
this.has = function(value){
return items.hasOwnProperty(value);
};
//清空集合 true
this.clear = function(){
items = {};
size = 0;
return true;
};
//集合大小 Number
this.size = function(){
return size;
};
//集合中的元素列表 Object(Array)
this.values = function(){
return Object.keys(items);
};
}
//在构造器对象上定义了一系列集合运算方法 可以直接调用
//求交集 Object(Set)
Set.intersection = function(set1, set2){
var res = new Set(),
temp = set1.values();
for(var i in temp){
if(set2.has(temp[i]))
res.add(temp[i]);
}
return res;
}
//求并集 Object(Set)
Set.union = function(set1, set2){
var res = new Set(),
temp = set1.values(),
temp2 = set2.values();
for(var i in temp)
res.add(temp[i]);
for(var j in temp2)
res.add(temp2[j]);
return res;
}
//求差集set1-set2 Object(Set)
Set.difference = function(set1, set2){
var res = new Set(),
temp = set1.values();
for(var i in temp)
if(!set2.has(temp[i]))
res.add[temp[i]];
return res;
}
//求笛卡儿积 这里用数组表示序偶 Object(Set)
Set.cartesianProduct = function(set1,set2){
var res = new Set(),
temp1 = set1.values(),
temp2 = set2.values();
for(var i = 0; i < temp1.length;i++)
for(var j = 0;j < temp2.length;j++)
res.add([temp1[i],temp2[j]]);
return res;
}
//求对称差 Object(Set)
Set.symmetricDifference = function(set1, set2){
return Set.union(Set.difference(set1, set2),Set.difference(set2,set1));
}
//set1是否是set2的子集 Boolean
Set.isSubset = function(set1, set2){ // if set1 is set2's subset, return true
var temp = set1.values();
for(var i in temp)
if(!set2.has(temp[i]))
return false;
return true;
}
//set1是否是set2的真子集 Boolean
Set.isProperSubset = function(set1, set2){ // if set1 is set2's proper subset, return true
if(set1.size() >= set2.size())
return false;
return Set.isSubset(set1, set2);
//another
//return Set.isSubset(set1, set2) && !Set.equality(set1, set2);
}
//两集合是否相等
Set.equality = function(set1, set2){
return Set.isSubset(set1, set2) && Set.isSubset(set2, set1);
}
其实在写面向对象系列后,有点小强迫症,特别想把方法都写进原型对象里。但是这里因为要通过闭包实现私有变量,必须将方法放进构造函数中。 如果非要把方法写在原型对象里的话,构造函数里也得定义对私有变量的访问接口方法,那感觉就真有点画蛇添足了。