-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathset.c
203 lines (133 loc) · 3.95 KB
/
set.c
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
197
198
199
200
201
202
203
//
// set.c
// Algorithms - set
//
// Created by YourtionGuo on 26/04/2017.
// Copyright © 2017 Yourtion. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "set.h"
#pragma mark - Public
void set_init(Set *set, int (*match)(const void *key1, const void *key2), void (*destroy)(void *data))
{
/// 初始化集合
list_init(set, destroy);
set->match = match;
return;
}
int set_insert(Set *set, const void *data)
{
/// 不允许插入已存在元素
if (set_is_member(set, data)) return 1;
/// 插入数据
return list_ins_next(set, list_tail(set), data);
}
int set_remove(Set *set, void **data)
{
ListElmt *member, *prev;
/// 查找待移除的元素
prev = NULL;
for (member = list_head(set); member != NULL; member = list_next(member)) {
if (set->match(*data, list_data(member))) break;
prev = member;
}
/// 找不到则返回 -1
if (member == NULL) return -1;
/// 移除成员
return list_rem_next(set, prev, data);
}
int set_union(Set *setu, const Set *set1, const Set *set2)
{
ListElmt *member;
void *data;
/// 初始化新集合
set_init(setu, set1->match, NULL);
/// 插入第一个集合的数据
for (member = list_head(set1); member != NULL; member = list_next(member)) {
data = list_data(member);
if (list_ins_next(setu, list_tail(setu), data) != 0) {
set_destroy(setu);
return -1;
}
}
/// 插入第二个集合的数据
for (member = list_head(set2); member != NULL; member = list_next(member)) {
if (set_is_member(set1, list_data(member))) {
/// 不插入 set1 存在的元素
continue;
} else {
data = list_data(member);
if (list_ins_next(setu, list_tail(setu), data) != 0) {
set_destroy(setu);
return -1;
}
}
}
return 0;
}
int set_intersection(Set *seti, const Set *set1, const Set *set2)
{
ListElmt *member;
void *data;
/// 初始化新集合
set_init(seti, set1->match, NULL);
/// 将两个集合都插入到集合中
for (member = list_head(set1); member != NULL; member = list_next(member)) {
if (set_is_member(set2, list_data(member))) {
data = list_data(member);
if (list_ins_next(seti, list_tail(seti), data) != 0) {
set_destroy(seti);
return -1;
}
}
}
return 0;
}
int set_difference(Set *setd, const Set *set1, const Set *set2)
{
ListElmt *member;
void *data;
/// 初始化新集合
set_init(setd, set1->match, NULL);
/// 将在 set1 但是不在 set2 中的元素插入集合
for (member = list_head(set1); member != NULL; member = list_next(member)) {
if (!set_is_member(set2, list_data(member))) {
data = list_data(member);
if (list_ins_next(setd, list_tail(setd), data) != 0) {
set_destroy(setd);
return -1;
}
}
}
return 0;
}
int set_is_member(const Set *set, const void *data)
{
ListElmt *member;
/// 判断元素是否在集合内
for (member = list_head(set); member != NULL; member = list_next(member)) {
if (set->match(data, list_data(member))) return 1;
}
return 0;
}
int set_is_subset(const Set *set1, const Set *set2)
{
ListElmt *member;
/// 快速判断,先判断集合大小
if (set_size(set1) > set_size(set2)) return 0;
/// 判断 set1 元素是否在 set2 中
for (member = list_head(set1); member != NULL; member = list_next(member)) {
if (!set_is_member(set2, list_data(member))) return 0;
}
return 1;
}
int set_is_equal(const Set *set1, const Set *set2)
{
/// 快速判断,先判断集合大小
if (set_size(set1) != set_size(set2)) return 0;
/// 如果集合大小相等,那么子集就是本身
return set_is_subset(set1, set2);
}