Edinburgh Speech Tools  2.1-release
EST_UList.cc
Go to the documentation of this file.
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1997,1998 */
6 /* All Rights Reserved. */
7 /* Permission is hereby granted, free of charge, to use and distribute */
8 /* this software and its documentation without restriction, including */
9 /* without limitation the rights to use, copy, modify, merge, publish, */
10 /* distribute, sublicense, and/or sell copies of this work, and to */
11 /* permit persons to whom this work is furnished to do so, subject to */
12 /* the following conditions: */
13 /* 1. The code must retain the above copyright notice, this list of */
14 /* conditions and the following disclaimer. */
15 /* 2. Any modifications must be clearly marked as such. */
16 /* 3. Original authors' names are not deleted. */
17 /* 4. The authors' names are not used to endorse or promote products */
18 /* derived from this software without specific prior written */
19 /* permission. */
20 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
21 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
22 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
23 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
24 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
25 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
26 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
27 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
28 /* THIS SOFTWARE. */
29 /* */
30 /*************************************************************************/
31 /* */
32 /* Author: Richard Caley (rjc@cstr.ed.ac.uk) */
33 /* Date: Mon Jul 21 1997 */
34 /* -------------------------------------------------------------------- */
35 /* Untyped list used as the basis of the TList class */
36 /* */
37 /*************************************************************************/
38 #include <EST_UList.h>
39 
40 using namespace std;
41 
42 void EST_UList::clear_and_free(void (*item_free)(EST_UItem *p))
43 {
44  EST_UItem *q, *np;
45 
46  for (q=head(); q != 0; q = np)
47  {
48  np=q->next();
49  if (item_free)
50  item_free(q);
51  else
52  delete q;
53  }
54  h = t = 0;
55 }
56 
57 int EST_UList::length() const
58 {
59  EST_UItem *ptr;
60  int n = 0;
61 
62  for (ptr = head(); ptr != 0; ptr = ptr->next())
63  ++n;
64  return n;
65 }
66 
67 int EST_UList::index(EST_UItem *item) const
68 {
69  EST_UItem *ptr;
70  int n = 0;
71 
72  for (ptr = head(); ptr != 0; ptr = ptr->next(), ++n)
73  if (item == ptr)
74  return n;
75 
76  return -1;
77 }
78 
80 {
81  EST_UItem *ptr;
82  int i;
83 
84  for (i = 0, ptr = head(); ptr != 0; ptr = ptr->next(), ++i)
85  if (i == n)
86  return ptr;
87 
88  cerr << "Requested item #" << n << " off end of list" << endl;
89  return head();
90 }
91 
93  void (*free_item)(EST_UItem *item))
94 {
95  if (item == 0)
96  return 0;
97 
98  EST_UItem *prev = item->p;
99  if (item->p == 0) // at start
100  h = item->n;
101  else
102  item->p->n = item->n;
103  if (item->n == 0) // at end
104  t = item->p;
105  else
106  item->n->p = item->p;
107 
108  if (free_item)
109  free_item(item);
110  else
111  delete item;
112 
113  return prev;
114 }
115 
117  void (*item_free)(EST_UItem *item))
118 {
119  return remove(nth_pointer(n), item_free);
120 }
121 
122 // This should check if the incoming prev_item actually is in the list
123 
125 {
126  if (new_item == 0)
127  return new_item;
128  if (prev_item == 0) // insert it at start of list
129  {
130  new_item->n = h;
131  h = new_item;
132  }
133  else
134  {
135  new_item->n = prev_item->n;
136  prev_item->n = new_item;
137  }
138  new_item->p = prev_item;
139  if (new_item->n == 0)
140  t = new_item;
141  else
142  new_item->n->p = new_item;
143 
144  return new_item;
145 }
146 
148 {
149  if (new_item == 0)
150  return new_item;
151  if (next_item == 0) // put it on the end of the list
152  {
153  new_item->p = t;
154  t = new_item;
155  }
156  else
157  {
158  new_item->p = next_item->p;
159  next_item->p = new_item;
160  }
161  new_item->n = next_item;
162  if (new_item->p == 0)
163  h = new_item;
164  else
165  new_item->p->n = new_item;
166 
167  return next_item;
168 }
169 
171 {
172 
173  if (a==b)
174  return;
175 
176  if ((a==0) || (b==0))
177  {
178  cerr << "EST_UList:exchange: can't exchange NULL items" << endl;
179  return;
180  }
181 
182  // I know this isn't very readable but there are eight pointers
183  // that need to be changed, and half of them are trivial back pointers
184  // care need only be taken when b and a are adjacent, this actual
185  // sets p and n twice if they are adjacent but still gets the right answer
186  EST_UItem *ap=a->p,*an=a->n,*bn=b->n,*bp=b->p;
187 
188  a->n = bn == a ? b : bn;
189  if (a->n)
190  a->n->p = a;
191  a->p = bp == a ? b : bp;
192  if (a->p)
193  a->p->n = a;
194 
195  b->n = an == b ? a : an;
196  if (b->n)
197  b->n->p = b;
198  b->p = ap == b ? a : ap;
199  if (b->p)
200  b->p->n = b;
201 
202  // Fix t and h
203  if (a == h)
204  h = b;
205  else if (b == h)
206  h = a;
207  else if (a == t)
208  t = b;
209  else if (b == t)
210  t = a;
211 
212 }
213 
214 void EST_UList::exchange(int i, int j)
215 {
216 
217  EST_UItem *p;
218  EST_UItem *a=0,*b=0;
219  int k;
220 
221  for (k=0,p = head(); p != 0; p = p->next(),k++)
222  {
223  if(i==k)
224  a = p;
225  if(j==k)
226  b = p;
227  }
228 
229  if ((a==0) || (b==0))
230  {
231  cerr << "EST_UList:exchange: can't exchange items " << i <<
232  " and " << j << " (off end of list)" << endl;
233  return;
234  }
235 
236  exchange(a,b);
237 }
238 
240 {
241  EST_UItem *p,*q;
242 
243  for (p=head(); p != 0; p=q)
244  {
245  q = p->n;
246  p->n = p->p;
247  p->p = q;
248  }
249  q = h;
250  h = t;
251  t = q;
252 }
253 
255 {
256 
257  if (new_item == 0) return;
258 
259  new_item->n = 0;
260  new_item->p = t;
261  if (t == 0)
262  h = new_item;
263  else
264  t->n = new_item;
265  t = new_item;
266 }
267 
269 {
270  if (new_item == 0) return;
271 
272  new_item->p = 0;
273  new_item->n = h;
274  if (h == 0)
275  t = new_item;
276  else
277  h->p = new_item;
278  h = new_item;
279 }
280 
282  const EST_UList &b,
283  bool (*eq)(const EST_UItem *item1, const EST_UItem *item2))
284 {
285  EST_UItem *p,*q;
286  q=b.head();
287  for (p = a.head(); p != NULL; p = p->next()){
288  if(q == NULL)
289  return false;
290  if(eq(q, p))
291  q=q->next();
292  else
293  return false;
294  }
295 
296  if(q == NULL)
297  return true;
298  else
299  return false;
300 }
301 
303  const EST_UItem &val,
304  bool (*eq)(const EST_UItem *item1, const EST_UItem *item2))
305 {
306 
307  EST_UItem *ptr;
308  int n = 0;
309 
310  for (ptr = l.head(); ptr != 0; ptr = ptr->next(), ++n)
311  if (eq(&val,ptr))
312  return n;
313 
314  return -1;
315 }
316 
318  bool (*gt)(const EST_UItem *item1,
319  const EST_UItem *item2))
320 {
321 
322  // just bubble sort for now
323  // use EST_String::operator > for comparisons
324 
325  EST_UItem *l_ptr,*m_ptr;
326  bool sorted=false;
327 
328  while(!sorted){
329  sorted=true;
330 
331  for(l_ptr=l.head(); l_ptr != 0; l_ptr=l_ptr->next()){
332 
333  m_ptr=l_ptr->next();
334  if(m_ptr != 0)
335  if(gt(l_ptr, m_ptr)){
336  l.exchange(l_ptr,m_ptr);
337  sorted=false;
338  }
339  }
340  }
341 
342 }
343 
344 // quicksort from 'Algorithms'
345 // by Cormen, Leiserson & Rivest
346 
347 static EST_UItem *partition(EST_UItem *p, EST_UItem *r,
348  bool (*gt)(const EST_UItem *item1, const EST_UItem *item2),
349  void (*exchange)(EST_UItem *item1, EST_UItem *item2))
350 {
351  // this can be tidied up / sped up
352 
353  EST_UItem *i,*j,*i2,*j2;
354  EST_UItem *x = p;
355 
356  i = p;
357  j = r;
358 
359  while(true){
360 
361  while(gt(j, x) )
362  j = j->prev();
363 
364  while(gt(x, i))
365  i = i->next();
366 
367  if((i != j) && (i->prev() != j)){
368  i2=i;
369  j2=j;
370  i=i->next();
371  j=j->prev();
372  exchange(i2,j2);
373 
374  }else
375  return j;
376 
377  }
378  return NULL;
379 }
380 
381 
382 static void qsort_sub(EST_UList &l, EST_UItem *p, EST_UItem *r,
383  bool (*gt)(const EST_UItem *item1, const EST_UItem *item2),
384  void (*exchange)(EST_UItem *item1, EST_UItem *item2))
385 {
386  EST_UItem *q;
387  if(p != r){
388  q = partition(p,r, gt, exchange);
389  qsort_sub(l,p,q, gt, exchange);
390  qsort_sub(l,q->next(),r, gt, exchange);
391  }
392 }
393 
395  bool (*gt)(const EST_UItem *item1, const EST_UItem *item2),
396  void (*exchange)(EST_UItem *item1, EST_UItem *item2))
397 {
398  qsort_sub(l,l.head(),l.tail(), gt, exchange);
399 }
400 
401 
403  bool (*eq)(const EST_UItem *item1, const EST_UItem *item2),
404  bool (*gt)(const EST_UItem *item1, const EST_UItem *item2),
405  void (*item_free)(EST_UItem *item))
406 {
407  // as sort(..) but delete any repeated items
408 
409  EST_UItem *l_ptr,*m_ptr;
410  bool sorted=false;
411 
412  while(!sorted){
413  sorted=true;
414 
415  for(l_ptr=l.head(); l_ptr != 0; l_ptr=l_ptr->next()){
416 
417  m_ptr=l_ptr->next();
418  if(m_ptr != 0)
419  {
420  if(gt(l_ptr, m_ptr)){
421  l.exchange(l_ptr,m_ptr);
422  sorted=false;
423  } else if(eq(l_ptr, m_ptr)){
424  l.remove(m_ptr, item_free);
425  sorted=false;
426  }
427  }
428  }
429  }
430 }
431 
433  bool (*eq)(const EST_UItem *item1, const EST_UItem *item2),
434  bool (*gt)(const EST_UItem *item1, const EST_UItem *item2),
435  void (*item_free)(EST_UItem *item))
436 {
437  // keep all unique items in l, and add any new items from m to l
438 
439  EST_UItem *l_ptr,*m_ptr;
440  bool flag;
441 
442  // make sure
443  sort_unique(l, eq, gt, item_free);
444 
445  for(m_ptr=m.head(); m_ptr != 0; m_ptr=m_ptr->next()){
446 
447  // try and put item from m in list
448  flag=false;
449  for(l_ptr=l.head(); l_ptr != 0; l_ptr=l_ptr->next()){
450  if( gt(l_ptr, m_ptr) ){
451  l.insert_before(l_ptr, m_ptr);
452  flag=true;
453  break;
454  }else if( eq(m_ptr, l_ptr) ){
455  flag=true;
456  break;
457  }
458  }
459  // or try and append it
460  if(!flag && ( gt(m_ptr, l.tail()) ) )
461  l.append(m_ptr);
462  }
463 }
EST_Item * next_item(const EST_Item *node)
Definition: EST_Item.h:427
EST_UItem * remove(EST_UItem *ptr, void(*item_free)(EST_UItem *item))
Definition: EST_UList.cc:92
void sort_unique(EST_TList< T > &l)
Definition: EST_TList.h:317
EST_UItem * prev()
Definition: EST_UList.h:56
STATIC STATUS exchange()
Definition: editline.c:1742
void clear_and_free(void(*item_free)(EST_UItem *item))
Definition: EST_UList.cc:42
EST_UItem * next()
Definition: EST_UList.h:55
void reverse()
Definition: EST_UList.cc:239
static void merge_sort_unique(EST_UList &l, EST_UList &m, bool(*eq)(const EST_UItem *item1, const EST_UItem *item2), bool(*gt)(const EST_UItem *item1, const EST_UItem *item2), void(*item_free)(EST_UItem *item))
Definition: EST_UList.cc:432
EST_UItem * n
Definition: EST_UList.h:53
EST_UItem * p
Definition: EST_UList.h:54
NULL
Definition: EST_WFST.cc:55
static void sort(EST_UList &a, bool(*gt)(const EST_UItem *item1, const EST_UItem *item2))
Definition: EST_UList.cc:317
EST_UItem * tail() const
Definition: EST_UList.h:99
void prepend(EST_UItem *item)
Definition: EST_UList.cc:268
int length() const
Definition: EST_UList.cc:57
void exchange(EST_UItem *a, EST_UItem *b)
Definition: EST_UList.cc:170
void append(EST_UItem *item)
Definition: EST_UList.cc:254
EST_UItem * insert_before(EST_UItem *ptr, EST_UItem *new_item)
Definition: EST_UList.cc:147
EST_UItem * head() const
Definition: EST_UList.h:97
static void qsort(EST_UList &a, bool(*gt)(const EST_UItem *item1, const EST_UItem *item2), void(*exchange)(EST_UItem *item1, EST_UItem *item2))
Definition: EST_UList.cc:394
static void sort_unique(EST_UList &l, bool(*eq)(const EST_UItem *item1, const EST_UItem *item2), bool(*gt)(const EST_UItem *item1, const EST_UItem *item2), void(*item_free)(EST_UItem *item))
Definition: EST_UList.cc:402
EST_UItem * nth_pointer(int n) const
Definition: EST_UList.cc:79
EST_UItem * insert_after(EST_UItem *ptr, EST_UItem *new_item)
Definition: EST_UList.cc:124
int index(EST_UItem *item) const
Definition: EST_UList.cc:67
static bool operator_eq(const EST_UList &a, const EST_UList &b, bool(*eq)(const EST_UItem *item1, const EST_UItem *item2))
Definition: EST_UList.cc:281