BSD 3 development
[unix-history] / usr / src / cmd / struct / 3.reach.c
CommitLineData
42d6e430
BJ
1#include <stdio.h>
2#
3/*
4set REACH[v] = w if w is only node outside subtree of v which is reached from within
5 subtree of v, REACH[v] = UNDEFINED otherwise
6*/
7#include "def.h"
8
9/* strategy in obtaining REACH(v) for each node v:
10Since only need to know whether there is exactly one exit from subtree of v,
11need keep track only of 2 farthest exits from each subtree rather than all exits.
12The first may be the unique exit, while the second is used when the children
13of a node has the same first exit.
14To obtain 2 farthest exits of v, look at 2 farthest exits of children of v and
15the nodes entered by arcs from v. Farthest exits are identified by numbering
16the nodes from -2 to -(accessnum-2) starting at the bottom left corner of tree
17using procedure number(). The farthest exit from the subtree of v is the one
18with the least number according NUM to this numbering. If a node w is an exit from the
19subtree of v, then NUM(w) < NUM(v). The negative numbers allow NUM(v) to be stored
20in the same location as REACH(v). REACH(w) may already be set when an arc (v,w) to a child
21is searched, but the negative numbering is consistent, i.e. NUM(v) < NUM(w) in this case
22as in other cases where w is not an exit from the subtree of v.
23*/
24
25struct pair {
26 int smallest;
27 int second;
28 };
29
30
31getreach() /* obtain REACH(v) for each node v */
32 {
33 VERT v;
34 struct pair *pr;
35 for (v = 0; v < nodenum; ++v)
36 REACH(v) = UNDEFINED;
37 number(START);
38 for (v = START; DEFINED(v); v = RSIB(v))
39 {
40 pr = exits(v); /* need to free the space for pr */
41 chfree(pr,sizeof(*pr));
42 }
43 }
44
45
46exits(v) /* set REACH(v) = w if w is only node outside subtree of v which is reached from within
47 subtree of v, leave REACH(v) UNDEFINED otherwise */
48VERT v;
49 {
50 struct pair *vpair, *chpair;
51 VERT w,t;
52 int i;
53 vpair = challoc(sizeof(*vpair));
54 vpair ->smallest = vpair ->second = UNDEFINED;
55 for (i = 0; i < CHILDNUM(v); ++i)
56 {
57 w = LCHILD(v,i);
58 if (!DEFINED(w)) continue;
59 for (t = w; DEFINED(t); t = RSIB(t))
60 {
61 chpair = exits(t);
62
63 /* set vpair->smallest,second to two smallest of vpair->smallest,second,
64 chpair->smallest,second */
65 if (inspr(chpair->smallest,vpair))
66 inspr(chpair->second,vpair);
67 chfree(chpair, sizeof(*chpair));
68 }
69 }
70 for (i = 0; i < ARCNUM(v); ++i)
71 {
72 w = ARC(v,i);
73 if (!DEFINED(w)) continue;
74 inspr(w,vpair);
75 }
76 /* throw out nodes in subtree of v */
77 if (NUM(vpair->second) >= NUM(v))
78 {
79 vpair->second = UNDEFINED;
80 if (NUM(vpair->smallest) >= NUM(v))
81 vpair->smallest = UNDEFINED;
82 }
83 if (vpair->second == UNDEFINED)
84 REACH(v) = vpair->smallest; /* vpair->smallest possibly UNDEFINED */
85 else
86 REACH(v) = UNDEFINED;
87 return(vpair);
88 }
89
90
91 /* number nodes from -2 to -(accessnum+2) starting at bottom left corner of tree */
92number(v)
93VERT v;
94 {
95 int i;
96 VERT w;
97 static int count;
98 for (i = 0; i < CHILDNUM(v); ++i)
99 {
100 w = LCHILD(v,i);
101 if (DEFINED(w))
102 number(w);
103 }
104 SETNUM(v,count-2);
105 --count;
106 if (DEFINED(RSIB(v)))
107 number(RSIB(v));
108 }
109
110
111NUM(v)
112VERT v;
113 {
114 if (!DEFINED(v)) return(UNDEFINED);
115 return(REACH(v));
116 }
117
118SETNUM(v,count)
119VERT v; int count;
120 {
121 /* this reuses REACH to save space;
122 /* appears to be no conflict with setting true value of REACH later */
123 REACH(v) = count;
124 }
125
126
127LOGICAL inspr(w,pr) /* insert w in order in pr, return TRUE if <= smaller of pr */
128 /* don't insert duplicates */
129VERT w;
130struct pair *pr;
131 {
132 if (w == pr-> smallest) return(TRUE);
133 if (NUM(w) < NUM(pr->smallest))
134 {
135 pr->second = pr->smallest;
136 pr->smallest = w;
137 return(TRUE);
138 }
139 if (w == pr->second) return(FALSE);
140 if (NUM(w) < NUM(pr->second))
141 pr->second = w;
142 return(FALSE);
143 }