上一篇《TypeScript 数据结构与算法:链表》实现了 Typescript
中链表的数据结构与算法,本篇继续实现集合。
集合
是由一组无序且唯一(即不能重复)的项组成的。该数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中。
集合(Set
)之间的运算包括并集、交集、差集等,如下图所示:
数据结构
集合
一个集合中,应该有以下方法:
add(element)
:向集合添加一个新元素。
delete(element)
:从集合移除一个元素。
has(element)
:如果元素在集合中,返回 true
,否则返回 false
。
clear()
:移除集合中的所有元素。
size()
:返回集合所包含元素的数量。它与数组的 length
属性类似。
values()
:返回一个包含集合中所有值(元素)的数组。
union(otherSet)
:返回与其他集合的并集。
intersection(otherSet)
:返回与其他集合的交集。
difference(otherSet)
:返回与其他集合的差集。
isSubsetOf(otherSet)
:返回是否为其他集合的子集。
在 ES2015
后,已经存在原生的 Set
数据结构了,但是没有上面所述的所有方法,所以以原生 Set
为基础来构造一个 CustomSet
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
| export default class CustomSet<T> { private items: Set<T>;
constructor(array?: T[]) { this.items = new Set(array); }
add(element: T): boolean { if (!this.has(element)) { this.items.add(element); return true; } return false; }
delete(element: T): boolean { if (this.has(element)) { return this.items.delete(element); } return false; }
has(element: T): boolean { return this.items.has(element); }
values(): T[] { return [...this.items]; }
union(otherSet: CustomSet<T>): CustomSet<T> { const unionSet = new CustomSet<T>();
this.values().forEach((value) => unionSet.add(value)); otherSet.values().forEach((value) => unionSet.add(value));
return unionSet; }
intersection(otherSet: CustomSet<T>): CustomSet<T> { const intersectionSet = new CustomSet<T>();
this.values() .filter((v) => otherSet.has(v)) .forEach((v) => { intersectionSet.add(v); });
return intersectionSet; }
difference(otherSet: CustomSet<T>): CustomSet<T> { const differenceSet = new CustomSet<T>();
this.values() .filter((v) => !otherSet.has(v)) .forEach((v) => { differenceSet.add(v); });
return differenceSet; }
isSubsetOf(otherSet: CustomSet<T>): boolean { if (this.size() > otherSet.size()) { return false; }
let isSubset = true; this.values().forEach((value) => { if (!otherSet.has(value)) { isSubset = false; } });
return isSubset; }
isEmpty(): boolean { return this.size() === 0; }
size(): number { return this.items.size; }
clear() { this.items = new Set(); }
toString(): string { return `${this.values()}`; } }
|
多重集
集合数据结构不允许存在重复的元素。但是,在数学中有一个叫作 多重集
的概念,允许我们向集合中插入重复元素。多重集(MultiSet
)在计算集合中元素的出现次数时很有用。
多重集有一些方法和普通集合有区别:
count(element)
:返回集合中指定元素的数目。
set(element, count)
:将集合中指定元素设为 count
个。
add(element, count)
:向集合添加 count
个指定元素。
remove(element, count)
:在集合删除 count
个指定元素。
delete(element)
:从集合移除所有指定元素。
dimension()
:返回集合所包含元素的种类数。它与数组的 length
属性类似。
具体实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
| export default class MultiSet<T> { private items: Map<T, number>;
constructor() { this.items = new Map(); }
has(element: T): boolean { return this.items.has(element); }
dimension(): number { return this.items.size; }
count(element: T): number { return this.items.get(element) ?? 0; }
delete(element: T): boolean { return this.items.delete(element); }
set(element: T, count: number): boolean { if (count <= 0) { return this.delete(element); } this.items.set(element, count); return true; }
add(element: T, count: number = 1): boolean { let newCount = this.count(element) + count; return this.set(element, newCount); }
remove(element: T, count: number = 1): boolean { return this.add(element, -count); }
isEmpty(): boolean { return this.dimension() === 0; }
values(): T[] { return Array.from(this.items.entries()).reduce((acc, cur) => { const [key, value] = cur; for (let i = 0; i < value; i++) { acc.push(key); } return acc; }, []); }
size(): number { return this.values().length; }
clear() { this.items = new Map(); }
union(otherSet: MultiSet<T>): MultiSet<T> { const unionSet = new MultiSet<T>();
this.values().forEach((value) => unionSet.add(value)); otherSet.values().forEach((value) => unionSet.add(value));
return unionSet; }
intersection(otherSet: MultiSet<T>): MultiSet<T> { const intersectionSet = new MultiSet<T>();
this.values() .filter((v) => otherSet.has(v)) .forEach((v) => { intersectionSet.add(v); });
return intersectionSet; }
difference(otherSet: MultiSet<T>): MultiSet<T> { const differenceSet = new MultiSet<T>();
this.values() .filter((v) => !otherSet.has(v)) .forEach((v) => { differenceSet.add(v); });
return differenceSet; }
isSubsetOf(otherSet: MultiSet<T>): boolean { if (this.size() > otherSet.size()) { return false; }
let isSubset = true; this.values().forEach((value) => { if (!otherSet.has(value)) { isSubset = false; } });
return isSubset; }
toString(): string { return `${this.values()}`; } }
|
下一篇来分析字典
。
前端记事本,不定期更新,欢迎关注!