Skip to content

Commit 434acc6

Browse files
committed
增加集合结构的封装和文档
1 parent 63bf97c commit 434acc6

File tree

4 files changed

+470
-0
lines changed

4 files changed

+470
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- [JavaScript 数据结构与算法(五)优先队列](assets/doc/05_JavaScript数据结构与算法(五)优先队列.md)
1818
- [JavaScript 数据结构与算法(六)单向链表](assets/doc/06_JavaScript数据结构与算法(六)单向链表.md)
1919
- [JavaScript 数据结构与算法(七)双向链表](assets/doc/07_JavaScript数据结构与算法(七)双向链表.md)
20+
- [JavaScript 数据结构与算法(八)集合](assets/doc/08_JavaScript数据结构与算法(八)集合.md)
2021

2122
## 测试环境
2223

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
# JavaScript 数据结构与算法(八)集合
2+
3+
## 集合
4+
5+
几乎每种编程语言中,都有集合结构。集合比较常见的实现方式是哈希表,这里使用 JavaScript 的 Object 进行封装。
6+
7+
### 集合特点
8+
9+
- 集合通常是由一组**无序的****不能重复的**元素构成。
10+
11+
- 数学中常指的集合中的元素是可以重复的,但是计算机中集合的元素不能重复。
12+
13+
- 集合是特殊的数组。
14+
- 特殊之处在于里面的元素没有顺序,也不能重复。
15+
- 没有顺序意味着不能通过下标值进行访问,不能重复意味着相同的对象在集合中只会存在一份。
16+
17+
### 封装集合
18+
19+
ES6 中的 `Set` 就是一个集合类,这里我们重新封装一个 `Set` 类,了解集合的底层实现。
20+
21+
#### 集合常见的操作
22+
23+
- `add(value)` 向集合添加一个新的项。
24+
- `remove(value)` 从集合移除一个值。
25+
- `has(value)` 如果值在集合中,返回 true,否则返回 false。
26+
- `clear()` 移除集合中的所有项。
27+
- `size()` 返回集合所包含元素的数量。与数组的 length 属性类似。
28+
- `values()` 返回一个包含集合中所有值的数组。
29+
- 还有其他的方法,用的不多,这里不做封装。
30+
31+
#### 代码实现
32+
33+
```js
34+
// 集合结构的封装
35+
class Set {
36+
constructor() {
37+
this.items = {};
38+
}
39+
40+
// has(value) 判断集合中是否存在 value 值,存在返回 true,否则返回 false
41+
has(value) {
42+
return this.items.hasOwnProperty(value);
43+
}
44+
45+
// add(value) 往集合中添加 value
46+
add(value) {
47+
if (this.has(value)) return false;
48+
this.items[value] = value;
49+
return true;
50+
}
51+
52+
// remove(value) 删除集合中指定的 value
53+
remove(value) {
54+
// 如果集合不存在该 value,返回 false
55+
if (!this.has(value)) return false;
56+
delete this.items[value];
57+
}
58+
59+
// clear() 清空集合中所有 value
60+
clear() {
61+
this.items = {};
62+
}
63+
64+
// size() 获取集合中的 value 个数
65+
size() {
66+
return Object.keys(this.items).length;
67+
}
68+
69+
// values() 获取集合中所有的 value
70+
values() {
71+
return Object.keys(this.items);
72+
}
73+
}
74+
```
75+
76+
#### 代码测试
77+
78+
```js
79+
const set = new Set();
80+
81+
// add() 测试
82+
set.add("abc");
83+
set.add("abc");
84+
set.add("123");
85+
set.add("zxc");
86+
console.log(set); //--> {items: {123: "123", abc: "abc", zxc: "zxc"}}
87+
88+
// has() 测试
89+
console.log(set.has("123")); //--> true
90+
console.log(set.has("456")); //--> false
91+
92+
// remove() 测试
93+
set.remove("abc");
94+
console.log(set); //--> {items: {123: "123", zxc: "zxc"}}
95+
96+
// size() 测试
97+
console.log(set.size()); //--> 2
98+
99+
// values() 测试
100+
console.log(set.values()); //--> ["123", "zxc"]
101+
102+
// clear() 测试
103+
set.clear();
104+
console.log(set.values()); //--> []
105+
```
106+
107+
### 集合间的操作
108+
109+
- 并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。
110+
- 交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。
111+
- 差集:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
112+
- 子集:验证一个给定集合是否是另一个集合的子集。
113+
114+
![](https://user-images.githubusercontent.com/24516169/88532735-b1069a00-d037-11ea-9ece-e19b2b8a09e2.png)
115+
116+
#### 并集的实现
117+
118+
```js
119+
// union() 求两个集合的并集
120+
union(otherSet) {
121+
// 1、创建一个新集合
122+
let unionSet = new Set();
123+
124+
// 2、将当前集合(this)的所有 value,添加到新集合(unionSet)中
125+
for (let value of this.values()) {
126+
unionSet.add(value);
127+
}
128+
129+
// 3、将 otherSet 集合的所有 value,添加到新集合(unionSet)中
130+
for (let value of otherSet.values()) {
131+
unionSet.add(value); // add() 已经有重复判断
132+
}
133+
134+
return unionSet;
135+
}
136+
```
137+
138+
#### 交集的实现
139+
140+
```js
141+
// intersection() 求两个集合的交集
142+
intersection(otherSet) {
143+
144+
// 1、创建一个新集合
145+
let intersectionSet = new Set();
146+
147+
// 2、从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在
148+
for (let value of this.values()) {
149+
if (otherSet.has(value)) {
150+
intersectionSet.add(value);
151+
}
152+
}
153+
154+
return intersectionSet;
155+
}
156+
```
157+
158+
#### 差集的实现
159+
160+
```js
161+
// difference() 差集
162+
difference(otherSet) {
163+
164+
// 1、创建一个新集合
165+
let differenceSet = new Set();
166+
167+
// 2、从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在,不存在的即为差集
168+
for (let value of this.values()) {
169+
if (!otherSet.has(value)) {
170+
differenceSet.add(value);
171+
}
172+
}
173+
174+
return differenceSet;
175+
}
176+
```
177+
178+
#### 子集的实现
179+
180+
```js
181+
// subset() 子集
182+
subset(otherSet) {
183+
184+
// 从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在,有不存在的返回 false
185+
// 遍历完所有的,返回 true
186+
for (let value of this.values()) {
187+
if (!otherSet.has(value)) {
188+
return false;
189+
}
190+
}
191+
return true;
192+
}
193+
```
194+
195+
### 集合的完整实现
196+
197+
```js
198+
// 集合结构的封装
199+
export default class Set {
200+
201+
constructor() {
202+
this.items = {};
203+
}
204+
205+
// has(value) 判断集合中是否存在 value 值,存在返回 true,否则返回 false
206+
has(value) {
207+
return this.items.hasOwnProperty(value);
208+
}
209+
210+
// add(value) 往集合中添加 value
211+
add(value) {
212+
if (this.has(value)) return false;
213+
this.items[value] = value;
214+
return true;
215+
}
216+
217+
// remove(value) 删除集合中指定的 value
218+
remove(value) {
219+
// 如果集合不存在该 value,返回 false
220+
if (!this.has(value)) return false;
221+
delete this.items[value];
222+
}
223+
224+
// clear() 清空集合中所有 value
225+
clear() {
226+
this.items = {};
227+
}
228+
229+
// size() 获取集合中的 value 个数
230+
size() {
231+
return Object.keys(this.items).length;
232+
}
233+
234+
// values() 获取集合中所有的 value
235+
values() {
236+
return Object.keys(this.items);
237+
}
238+
239+
// ------- 集合间的操作 ------- //
240+
// union() 求两个集合的并集
241+
union(otherSet) {
242+
// 1、创建一个新集合
243+
let unionSet = new Set();
244+
245+
// 2、将当前集合(this)的所有 value,添加到新集合(unionSet)中
246+
for (let value of this.values()) {
247+
unionSet.add(value);
248+
}
249+
250+
// 3、将 otherSet 集合的所有 value,添加到新集合(unionSet)中
251+
for (let value of otherSet.values()) {
252+
unionSet.add(value); // add() 已经有重复判断
253+
}
254+
255+
return unionSet;
256+
}
257+
258+
// intersection() 求两个集合的交集
259+
intersection(otherSet) {
260+
261+
// 1、创建一个新集合
262+
let intersectionSet = new Set();
263+
264+
// 2、从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在
265+
for (let value of this.values()) {
266+
if (otherSet.has(value)) {
267+
intersectionSet.add(value);
268+
}
269+
}
270+
271+
return intersectionSet;
272+
}
273+
274+
// difference() 差集
275+
difference(otherSet) {
276+
277+
// 1、创建一个新集合
278+
let differenceSet = new Set();
279+
280+
// 2、从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在,不存在的即为差集
281+
for (let value of this.values()) {
282+
if (!otherSet.has(value)) {
283+
differenceSet.add(value);
284+
}
285+
}
286+
287+
return differenceSet;
288+
}
289+
290+
// subset() 子集
291+
subset(otherSet) {
292+
293+
// 从当前集合中取出每一个 value,判断是否在 otherSet 集合中存在,有不存在的返回 false
294+
// 遍历完所有的,返回 true
295+
for (let value of this.values()) {
296+
if (!otherSet.has(value)) {
297+
return false;
298+
}
299+
}
300+
return true;
301+
}
302+
303+
}
304+
```

src/Set/index.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Set from './set';
2+
3+
// ---------------- 封装的栈结构测试 ---------------- //
4+
console.log('// ----- 集合结构测试 START -----//');
5+
const set = new Set();
6+
7+
// add() 测试
8+
set.add('abc');
9+
set.add('abc');
10+
set.add('123');
11+
set.add('zxc');
12+
console.log(set); //--> {items: {123: "123", abc: "abc", zxc: "zxc"}}
13+
14+
// has() 测试
15+
console.log(set.has('123')); //--> true
16+
console.log(set.has('456')); //--> false
17+
18+
// remove() 测试
19+
set.remove('abc');
20+
console.log(set); //--> {items: {123: "123", zxc: "zxc"}}
21+
22+
// size() 测试
23+
console.log(set.size()); //--> 2
24+
25+
// values() 测试
26+
console.log(set.values()); //--> ["123", "zxc"]
27+
28+
// clear() 测试
29+
set.clear();
30+
console.log(set.values()); //--> []
31+
32+
// ------- 集合的操作测试 ------- //
33+
const setA = new Set();
34+
setA.add('111');
35+
setA.add('222');
36+
setA.add('333');
37+
38+
const setB = new Set();
39+
setB.add('111');
40+
setB.add('222');
41+
setB.add('aaa');
42+
setB.add('ccc');
43+
44+
// 求两个集合的并集 union() 测试
45+
console.log(setA.union(setB).values()); //--> ["111", "222", "333", "aaa", "ccc"]
46+
47+
// 求两个集合的交集 intersection() 测试
48+
console.log(setA.intersection(setB).values()); //--> ["111", "222"]
49+
50+
// 求集合 A 和 集合 B,集合 A 的差集,difference() 测试
51+
console.log(setA.difference(setB).values()); //--> ["333"]
52+
53+
// 求集合 A 是否为 集合 B 的 子集,subset() 测试
54+
console.log(setA.subset(setB)); //--> false
55+
56+
57+
console.log('// ----- 集合结构测试 END -----//');
58+
59+

0 commit comments

Comments
 (0)