Algorithmen & Datenstrukturen mit Java: Listen als einfach verkettete Listen |
1package ds.persistent.genlist;
2
3/** Implementation of single linked lists with generics.
4
5 This implementation is a PERSISTENT one.
6*/
7
8import java.util.Iterator;
9
10import static ds.util.Undef.undefined;
11
12public abstract class LinkedList<E>
13 implements Iterable<E> {
14
15 //----------------------------------------
16 // the smart constructors
17
18 // empty list
19 @SuppressWarnings("unchecked")
20 public static <E> LinkedList<E> empty() {
21 return
22 (LinkedList<E>)EMPTY;
23 }
24
25 // singleton list
26 public static <E> LinkedList<E> singleton(E e) {
27 LinkedList<E> l = empty();
28 return
29 l.cons(e);
30 }
31
32 // list from iterator
33 public static <E> LinkedList<E> fromIterator(Iterator<E> elems) {
34 if ( elems.hasNext() ) {
35 E info = elems.next();
36 return
37 fromIterator(elems).cons(info);
38 }
39 return
40 empty();
41 }
42
43 //----------------------------------------
44 // public methods
45
46 abstract public boolean isEmpty();
47 abstract public boolean member(E e);
48 abstract public int length();
49 abstract public E head();
50 abstract public LinkedList<E> tail();
51 abstract public E last();
52 abstract public LinkedList<E> init();
53 abstract public E at(int i);
54 /* destructive *
55 abstract public LinkedList<E> copy();
56 /**/
57
58 public LinkedList<E> append(E e) {
59 return
60 concat(singleton(e));
61 }
62
63 public LinkedList<E> cons(E e) {
64 return
65 new Node<E>(e, this);
66 }
67
68 abstract public LinkedList<E> concat(LinkedList<E> l2);
69
70 public LinkedList<E> reverse() {
71 LinkedList<E> l = empty();
72 return
73 reverse1(l);
74 }
75 abstract protected LinkedList<E> reverse1(LinkedList<E> res);
76
77 public Iterator<E> iterator() {
78 return
79 new ListIterator<E>(this);
80 }
81
82 public String toString() {
83 return
84 (new ListIterator<E>(this)).toString();
85 }
86
87 //----------------------------------------
88 // the empty list
89
90 // the "generic" empty list object, (the singleton has a raw type)
91
92 private static final LinkedList EMPTY
93 = new Empty<Object>();
94
95 // the singleton class for the empty list object
96
97 private static final
98 class Empty<E>
99 extends LinkedList<E> {
100
101 public boolean isEmpty() { return true; }
102 public boolean member(E e) { return false; }
103 public int length() { return 0; }
104
105 public E head() {
106 return undefined("head of empty list");
107 }
108 public LinkedList<E> tail() {
109 return undefined("tail of empty list");
110 }
111 public E last() {
112 return undefined("last of empty list");
113 }
114 public LinkedList<E> init() {
115 return undefined("init of empty list");
116 }
117 public E at(int i) {
118 return undefined("at of empty list");
119 }
120 public LinkedList<E> concat(LinkedList<E> l2) {
121 return
122 l2;
123 }
124 /* destructive *
125 public LinkedList<E> copy() {
126 return
127 this;
128 }
129 /**/
130
131 //----------------------------------------
132 // not public stuff
133
134 Empty() { }
135
136 protected LinkedList<E> reverse1(LinkedList<E> res) {
137 return
138 res;
139 }
140 }
141
142 //----------------------------------------
143 // the none empty list class
144
145 private static final
146 class Node<E>
147 extends LinkedList<E> {
148
149 public boolean isEmpty() { return false; }
150
151 public boolean member(E e) {
152 return
153 e.equals(info)
154 ||
155 next.member(e);
156 }
157
158 public int length() {
159 return
160 1 + next.length();
161 }
162
163 public E head() {
164 return
165 info;
166 }
167
168 public LinkedList<E> tail() {
169 return
170 next;
171 }
172
173 public E last() {
174 if ( next.isEmpty() )
175 return
176 info;
177 return
178 next.last();
179 }
180
181 public LinkedList<E> init() {
182 if ( next.isEmpty() )
183 return
184 empty();
185 return
186 setNext(next.init());
187 }
188
189 public E at(int i) {
190 if ( i == 0 )
191 return
192 info;
193 return
194 next.at(i - 1);
195 }
196
197 public LinkedList<E> concat(LinkedList<E> l2) {
198 return
199 setNext(next.concat(l2));
200 }
201
202 /* destructive *
203 public LinkedList<E> copy() {
204 return
205 next.copy().cons(info);
206 }
207 /**/
208
209 //----------------------------------------
210 // not public stuff
211
212 private final E info;
213 private
214 /* persistent */ final /**/
215 LinkedList<E> next;
216
217 Node(E i, LinkedList<E> n) {
218 info = i;
219 next = n;
220 ++cntNode;
221 }
222
223 protected LinkedList<E> reverse1(LinkedList<E> res) {
224 LinkedList<E> tmp = next;
225 return
226 tmp.reverse1(setNext(res));
227 }
228
229 LinkedList<E> setNext(LinkedList<E> next) {
230 /* persistent */
231 if ( next == this.next )
232 return
233 this;
234 return
235 next.cons(info);
236
237 /* destructive *
238 this.next = next;
239 return
240 this;
241 /**/
242 }
243 }
244
245 //----------------------------------------
246 // iterator class
247
248 private static
249 class ListIterator<E>
250 extends ds.util.Iterator<E> {
251
252 LinkedList<E> cur;
253
254 ListIterator(LinkedList<E> l) {
255 cur = l;
256 ++cntIter;
257 }
258
259 public boolean hasNext() {
260 return
261 ! cur.isEmpty();
262 }
263
264 public E next() {
265 if ( cur.isEmpty() )
266 return undefined("iterator exhausted");
267 {
268 E res = cur.head();
269 cur = cur.tail();
270 return
271 res;
272 }
273 }
274 }
275
276 //----------------------------------------
277 // profiling
278
279 private static int cntNode = 0;
280 private static int cntIter = 0;
281
282 public static String stats() {
283 return
284 "stats for ds.persistent.list.LinkedList:\n" +
285 "# new Node() : " + cntNode + "\n" +
286 "# new ListIterator() : " + cntIter + "\n";
287 }
288}
|
Letzte Änderung: 15.10.2015 | © Prof. Dr. Uwe Schmidt |