Initial revision
This commit is contained in:
208
util/ego/share/lset.c
Normal file
208
util/ego/share/lset.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/* L O N G S E T S
|
||||
*
|
||||
* L S E T . C
|
||||
*/
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "lset.h"
|
||||
#include "alloc.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
/* A 'long' set is represented as a linear list of 'elemholder'
|
||||
* records. Every such record contains a pointer to an element
|
||||
* of the set and to the next elemholder. An empty set is
|
||||
* represented as a null pointer.
|
||||
* An element of a long set must be of some pointer type or,
|
||||
* in any case, must have the size of a pointer. Note that
|
||||
* the strict typing rules are not obeyed here.
|
||||
* This package implements the usual operations on sets.
|
||||
* The name of every operation is preceeded by a 'L' to
|
||||
* distinguish it from the operation on 'compact' (bitvector)
|
||||
* sets with a similar name.
|
||||
*/
|
||||
|
||||
|
||||
lset Lempty_set()
|
||||
{
|
||||
return ((lset) 0);
|
||||
}
|
||||
|
||||
|
||||
bool Lis_elem(x,s)
|
||||
register Lelem_t x;
|
||||
register lset s;
|
||||
{
|
||||
|
||||
/* Search the list to see if x is an element of s */
|
||||
while (s != (elem_p) 0) {
|
||||
if (s->e_elem == x) {
|
||||
return TRUE;
|
||||
}
|
||||
s = s->e_next;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Ladd(x,s_p)
|
||||
Lelem_t x;
|
||||
lset *s_p;
|
||||
{
|
||||
/* add x to a set. Note that the set is given as in-out
|
||||
* parameter, because it may be changed.
|
||||
*/
|
||||
|
||||
elem_p t;
|
||||
|
||||
if (!Lis_elem(x,*s_p)) {
|
||||
t = newelem(); /* allocate a new elemholder */
|
||||
t->e_elem = x;
|
||||
t->e_next = *s_p; /* insert it at the head of the list */
|
||||
*s_p = t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Lremove(x,s_p)
|
||||
Lelem_t x;
|
||||
lset *s_p;
|
||||
{
|
||||
/* Remove x from a set. If x was not an element of
|
||||
* the set, nothing happens.
|
||||
*/
|
||||
|
||||
register elem_p *epp, ep;
|
||||
lset s;
|
||||
|
||||
s = *s_p;
|
||||
epp = &s;
|
||||
while ((ep = *epp) != (elem_p) 0) {
|
||||
if (ep->e_elem == x) {
|
||||
*epp = ep->e_next;
|
||||
oldelem(ep);
|
||||
break;
|
||||
} else {
|
||||
epp = &ep->e_next;
|
||||
}
|
||||
}
|
||||
*s_p = s;
|
||||
}
|
||||
|
||||
|
||||
/* The operations first, next and elem can be used to iterate
|
||||
* over a set. For example:
|
||||
* for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i,s) {
|
||||
* x = Lelem(i);
|
||||
* use x
|
||||
* }
|
||||
* which is like:
|
||||
* 'for all elements x of s do'
|
||||
* use x
|
||||
*/
|
||||
|
||||
|
||||
Lindex Lfirst(s)
|
||||
lset s;
|
||||
{
|
||||
return ((Lindex) s);
|
||||
/* Note that an index for long sets is just
|
||||
* a pointer to an elemholder.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
Lindex Lnext(i,s)
|
||||
Lindex i;
|
||||
lset s;
|
||||
{
|
||||
assert(i != (Lindex) 0);
|
||||
return (i->e_next);
|
||||
}
|
||||
|
||||
|
||||
Lelem_t Lelem(i)
|
||||
Lindex i;
|
||||
{
|
||||
return (i->e_elem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ljoin(s1,s2_p)
|
||||
lset s1,*s2_p;
|
||||
{
|
||||
/* Join two sets, assign the result to the second set
|
||||
* and delete the first set (i.e. the value of the
|
||||
* first set becomes undefined).
|
||||
*/
|
||||
|
||||
register elem_p *epp, ep;
|
||||
lset s2;
|
||||
|
||||
/* First all elements of s1 that are also an element of s2
|
||||
* are removed from the s1 list. The two resulting lists
|
||||
* (for s1 and s2) are linked (s1 first).
|
||||
* Note the usage of epp, which points to a pointer that
|
||||
* points to the next elemholder record of the list.
|
||||
*/
|
||||
|
||||
s2 = *s2_p;
|
||||
epp = &s1;
|
||||
while ((ep = *epp) != (elem_p) 0) {
|
||||
if (Lis_elem(ep->e_elem,s2)) {
|
||||
/* remove an element */
|
||||
*epp = ep->e_next;
|
||||
oldelem(ep);
|
||||
} else {
|
||||
epp = &ep->e_next;
|
||||
}
|
||||
}
|
||||
*epp = s2; /* last record of s1 (or s1 itself) now points
|
||||
* to first record of s2.
|
||||
*/
|
||||
*s2_p = s1;
|
||||
}
|
||||
|
||||
|
||||
Ldeleteset(s)
|
||||
lset s;
|
||||
{
|
||||
register elem_p ep, next;
|
||||
|
||||
for (ep = s; ep != (elem_p) 0; ep = next) {
|
||||
next = ep->e_next;
|
||||
oldelem(ep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Lis_subset(s1,s2)
|
||||
lset s1,s2;
|
||||
{
|
||||
/* See if s1 is a subset of s2 */
|
||||
|
||||
register Lindex i;
|
||||
|
||||
for (i = Lfirst(s1); i != (Lindex) 0; i = Lnext(i,s1)) {
|
||||
if (!Lis_elem(Lelem(i),s2)) return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
short Lnrelems(s)
|
||||
lset s;
|
||||
{
|
||||
/* Compute the number of elements of a set */
|
||||
|
||||
register elem_p ep;
|
||||
register short cnt;
|
||||
|
||||
cnt = 0;
|
||||
for (ep = s; ep != (elem_p) 0; ep = ep->e_next) {
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
Reference in New Issue
Block a user