-
Notifications
You must be signed in to change notification settings - Fork 8
/
set.c
169 lines (149 loc) · 3.13 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
// set.c ... simple, inefficient Set of Strings
// Written by John Shepherd, September 2015
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "set.h"
#define strEQ(s,t) (strcmp((s),(t)) == 0)
#define strLT(s,t) (strcmp((s),(t)) < 0)
typedef struct Node *Link;
typedef struct Node {
char *val;
Link next;
} Node;
typedef struct SetRep {
int nelems;
Link elems;
} SetRep;
// Function signatures
Set newSet();
void disposeSet(Set);
void insertInto(Set,char *);
void dropFrom(Set,char *);
int isElem(Set,char *);
int nElems(Set);
static Link newNode(char *);
static void disposeNode(Link);
static int findNode(Link,char *,Link *,Link *);
// newSet()
// - create an initially empty Set
Set newSet()
{
Set new = malloc(sizeof(SetRep));
assert(new != NULL);
new->nelems = 0;
new->elems = NULL;
return new;
}
// disposeSet(Set)
// - clean up memory associated with Set
void disposeSet(Set s)
{
if (s == NULL) return;
Link next, curr = s->elems;
while (curr != NULL) {
next = curr->next;
disposeNode(curr);
curr = next;
}
}
// insertInto(Set,Str)
// - ensure that Str is in Set
void insertInto(Set s, char *str)
{
assert(s != NULL);
Link curr, prev;
int found = findNode(s->elems,str,&curr,&prev);
if (found) return; // already in Set
Link new = newNode(str);
s->nelems++;
if (prev == NULL) {
// add at start of list of elems
new->next = s->elems;
s->elems = new;
}
else {
// add into list of elems
new->next = prev->next;
prev->next = new;
}
}
// dropFrom(Set,Str)
// - ensure that Str is not in Set
void dropFrom(Set s, char *str)
{
assert(s != NULL);
Link curr, prev;
int found = findNode(s->elems,str,&curr,&prev);
if (!found) return;
s->nelems--;
if (prev == NULL)
s->elems = curr->next;
else
prev->next = curr->next;
disposeNode(curr);
}
// isElem(Set,Str)
// - check whether Str is contained in Set
int isElem(Set s, char *str)
{
assert(s != NULL);
Link curr, prev;
return findNode(s->elems,str,&curr,&prev);
}
// nElems(Set)
// - return # elements in Set
int nElems(Set s)
{
assert(s != NULL);
return s->nelems;
}
// showSet(Set)
// - display Set (for debugging)
void showSet(Set s)
{
Link curr;
if (s->nelems == 0)
printf("Set is empty\n");
else {
printf("Set has %d elements:\n",s->nelems);
int id = 0;
curr = s->elems;
while (curr != NULL) {
printf("[%03d] %s\n", id, curr->val);
id++;
curr = curr->next;
}
}
}
// Helper functions
static Link newNode(char *str)
{
Link new = malloc(sizeof(Node));
assert(new != NULL);
new->val = strdup(str);
new->next = NULL;
return new;
}
static void disposeNode(Link curr)
{
assert(curr != NULL);
free(curr->val);
free(curr);
}
// findNode(L,Str)
// - finds where Str could be added into L
// - if already in L, curr->val == Str
// - if not already in L, curr and prev indicate where to insert
// - return value indicates whether Str found or not
static int findNode(Link list, char *str, Link *cur, Link *pre)
{
Link curr = list, prev = NULL;
while (curr != NULL && strLT(curr->val,str)) {
prev = curr;
curr = curr->next;
}
*cur = curr; *pre = prev;
return (curr != NULL && strEQ(str,curr->val));
}