-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSortedSet.cls
207 lines (176 loc) · 5.5 KB
/
SortedSet.cls
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
204
205
206
207
public class SortedSet {
//
// NOTE: This only works with PRIMITIVES, i.e. Integers, Strings, etc.
//
private Map<Object,Node> nodesByValue;
private Map<Integer,Node> nodesByOrder;
private Integer size;
public SortedSet() {
this.nodesByOrder = new Map<Integer,Node>();
this.nodesByValue = new Map<Object,Node>();
this.size = 0;
}
public class Node {
public Entry entry { public get; private set; }
public Integer order { public get; private set; }
public Node(Entry e, Integer order) {
this.entry = e;
this.order = order;
}
public Object value() { return entry.value; }
}
public Boolean add(Entry e) {
// Make sure that the Map does not contain the specified element
if (!nodesByValue.containsKey(e.value)) {
// Instantiate a new Node
Node n = new Node(e,size++);
nodesByOrder.put(n.order,n);
nodesByValue.put(e.value,n);
return true;
} else return false;
}
// @Override
public Boolean add(Object o) {
// Make sure that the Map does not contain the specified element
if (!nodesByValue.containsKey(o)) return add(new Entry(o));
else return false;
}
// @Override
public Boolean addAll(List<Object> l) {
Boolean addedAll = true;
for (Object o : l) {
if (!nodesByValue.containsKey(o)) add(o);
else if (addedAll == true) addedAll = false;
}
return addedAll;
}
// @Override
public Boolean addAll(Set<Object> l) {
Boolean addedAll = true;
for (Object o : l) {
if (!nodesByValue.containsKey(o)) add(o);
else if (addedAll == true) addedAll = false;
}
return addedAll;
}
// @Override
public Boolean addAll(List<Entry> entries) {
Boolean addedAll = true;
for (Entry e : entries) {
if (!nodesByValue.containsKey(e.value)) add(e);
else if (addedAll == true) addedAll = false;
}
return addedAll;
}
// Empty out our Sorted Set
// @Override
public void clear() {
size = 0;
nodesByValue.clear();
nodesByOrder.clear();
}
// @Override
public SortedSet deepClone() {
SortedSet newSS = new SortedSet();
newSS.addAll(entryList());
return newSS;
}
// @Override
public Boolean contains(Object e) {
return nodesByValue.containsKey(e);
}
// @Override
public Boolean isEmpty() {
return size == 0;
}
// Return a List view of all the entries in our set
public List<Entry> entryList() {
List<Entry> entries = new List<Entry>();
for (Integer i = 0; i < size; i++) entries.add(nodesByOrder.get(i).entry);
return entries;
}
// Remove the entry with the specified order
// @Override
public Object remove(Integer order) {
if (!nodesByOrder.containsKey(order)) {
// Remove the Node from nodesByOrder
Node n = nodesByOrder.remove(order);
// Remove this Node from nodesByValue
nodesByValue.remove(n.value());
// Decrement size
size--;
// Return the value
return n.value();
} else return null;
}
// Remove the entry with the specified value
// @Override
public Object remove(Object o) {
if (!nodesByValue.containsKey(o)) {
// Remove the Node from nodesByValue
Node n = nodesByValue.remove(o);
// Remove this Node from nodesByOrder
nodesByOrder.remove(n.order);
// Decrement size
size--;
// Return the value
return n.value();
} else return null;
}
//
// SORTED SET INTERFACE METHODS
//
// Return the last element in the Set
public Object last() { return nodesByOrder.get(size-1).value(); }
// Return the first element in the Set
public Object first() { return nodesByOrder.get(0).value(); }
// Returns a view of the portion of this set whose elements are strictly less than toElement.
public SortedSet headSet(Object toElement) {
// Find the entry corresponding to toElement
Node endNode = nodesByValue.get(toElement);
if (endNode == null) return null;
Integer endIndex = endNode.order;
// Instantiate a new SortedSet to return to the user
SortedSet headset = new SortedSet();
for (Integer i = 0; i < endIndex; i++) headset.add(nodesByOrder.get(i).entry);
return headset;
}
// Returns a view of the portion of this set whose elements are greater than or equal to fromElement.
public SortedSet tailSet(Object fromElement) {
// Find the entry corresponding to fromElement
Node startNode = nodesByValue.get(fromElement);
if (startNode == null) return null;
Integer startIndex = startNode.order;
// Instantiate a new SortedSet to return to the user
SortedSet tailset = new SortedSet();
for (Integer i = startIndex; i < size; i++) tailset.add(nodesByOrder.get(i).entry);
return tailset;
}
// Returns a view of the portion of this set whose elements range
// from fromElement (inclusive = fromInclusive)
// to toElement (inclusive = toInclusive).
public SortedSet subSet(Object fromElement, boolean fromInclusive, Object toElement, boolean toInclusive) {
// Find the entry corresponding to fromElement
Node startNode = nodesByValue.get(fromElement);
// Find the entry corresponding to toElement
Node endNode = nodesByValue.get(toElement);
if (startNode == null || endNode == null) return null;
Integer startIndex = startNode.order + (fromInclusive ? 0 : 1);
Integer endIndex = endNode.order + (toInclusive ? 1 : 0);
// Instantiate a new SortedSet to return to the user
SortedSet subset = new SortedSet();
for (Integer i = startIndex; i < endIndex; i++) subset.add(nodesByOrder.get(i).entry);
return subset;
}
// @Override
public Integer size() {
return size;
}
public class Entry {
//public Integer order;
public Object value;
public Entry(Object value) {
this.value = value;
}
}
}