Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/planarity/listcoll.c
4091 views
1
/*
2
Planarity-Related Graph Algorithms Project
3
Copyright (c) 1997-2010, John M. Boyer
4
All rights reserved. Includes a reference implementation of the following:
5
6
* John M. Boyer. "Simplified O(n) Algorithms for Planar Graph Embedding,
7
Kuratowski Subgraph Isolation, and Related Problems". Ph.D. Dissertation,
8
University of Victoria, 2001.
9
10
* John M. Boyer and Wendy J. Myrvold. "On the Cutting Edge: Simplified O(n)
11
Planarity by Edge Addition". Journal of Graph Algorithms and Applications,
12
Vol. 8, No. 3, pp. 241-273, 2004.
13
14
* John M. Boyer. "A New Method for Efficiently Generating Planar Graph
15
Visibility Representations". In P. Eades and P. Healy, editors,
16
Proceedings of the 13th International Conference on Graph Drawing 2005,
17
Lecture Notes Comput. Sci., Volume 3843, pp. 508-511, Springer-Verlag, 2006.
18
19
Redistribution and use in source and binary forms, with or without modification,
20
are permitted provided that the following conditions are met:
21
22
* Redistributions of source code must retain the above copyright notice, this
23
list of conditions and the following disclaimer.
24
25
* Redistributions in binary form must reproduce the above copyright notice, this
26
list of conditions and the following disclaimer in the documentation and/or
27
other materials provided with the distribution.
28
29
* Neither the name of the Planarity-Related Graph Algorithms Project nor the names
30
of its contributors may be used to endorse or promote products derived from this
31
software without specific prior written permission.
32
33
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
37
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
40
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
*/
44
45
#define _LISTCOLL_C
46
47
#include "appconst.h"
48
#include "listcoll.h"
49
#include <stdlib.h>
50
51
/*****************************************************************************
52
The data structure defined by this module manages a set of N objects
53
arranged as a collection of circular lists, each containing distinct
54
elements from the set.
55
56
On construction, LCNew() creates an array of N nodes, each containing a
57
prev and next pointer. The identity of the node is given by its array index.
58
Each node's prev and next pointers are set to NIL, indicating that the node
59
is not currently part of a list. LCReset() can be called to reset all
60
pointers to NIL.
61
62
The function LCFree() deallocates the collection of lists and clears the
63
pointer variable used to pass the collection.
64
65
An empty list is indicated by NIL. To begin a list with node I, call
66
LCPrepend() or LCAppend() with the NIL list and with I as the node. The prev
67
and next pointers in node I are set to I and I is returned as the head of
68
the list.
69
70
Future calls to LCPrepend() add a node J as the new first element of the list,
71
so the list given as input is pointed to by J's next, and J is returned as
72
the head of the list.
73
74
Future calls to LCAppend() add a node J as the new last element, so the prev
75
pointer of the list given as input will indicate node J, and the input list
76
is returned as the head of the list.
77
78
LCInsertAfter() adds a node immediately after a given anchor node.
79
80
LCInsertBefore() adds a node immediately before a given anchor node and has
81
the same effect on a list as LCPrepend().
82
83
The function LCDelete() removes a node I from a list L. If node I is in the
84
list alone, then its pointers are set to NIL, and NIL is returned as the list.
85
If node I is not alone in the list, but it is the head of the list (in other
86
words, I is equal to L), then L's sucessor is returned as the new head of the
87
list. Whether or not I equals L, node I is deleted by joining its predecessor
88
and successor nodes.
89
90
LCCopy() copies the contents of one collection to another if both are of
91
equal size.
92
93
LCGetNext() is used for forward iteration through a list in the collection.
94
The expected iteration pattern is first to process the node one has, then call
95
LCGetNext() to get the next node, so if the result of LCGetNext() would be the
96
head of the list, then NIL is returned instead. This simplifies most
97
coding operations involving LCGetNext().
98
99
LCGetPrev() is used for backward iteration through a list in the collection.
100
The expected iteration pattern is that the last list element will be obtained
101
by an initial call to LCGetPrev() with theNode equal to NIL. This call
102
should appear outside of the iteration loop. The iteration loop then
103
proceeds while the current node is not NIL. The loop body processes the
104
current node, then LCGetPrev() is called with theNode equal to the current
105
node. LCGetPrev() returns NIL if theNode is equal to theList. Otherwise,
106
the predecessor of theNode is returned.
107
108
*****************************************************************************/
109
110
/*****************************************************************************
111
LCNew()
112
*****************************************************************************/
113
114
listCollectionP LCNew(int N)
115
{
116
listCollectionP theListColl = NULL;
117
118
if (N <= 0) return theListColl;
119
120
theListColl = (listCollectionP) malloc(sizeof(listCollectionRec));
121
if (theListColl != NULL)
122
{
123
theListColl->List = (lcnode *) malloc(N*sizeof(lcnode));
124
if (theListColl->List == NULL)
125
{
126
free(theListColl);
127
theListColl = NULL;
128
}
129
else
130
{
131
theListColl->N = N;
132
LCReset(theListColl);
133
}
134
}
135
return theListColl;
136
}
137
138
/*****************************************************************************
139
LCFree()
140
*****************************************************************************/
141
142
void LCFree(listCollectionP *pListColl)
143
{
144
if (pListColl==NULL || *pListColl==NULL) return;
145
146
if ((*pListColl)->List != NULL)
147
free((*pListColl)->List);
148
149
free(*pListColl);
150
*pListColl = NULL;
151
}
152
153
/*****************************************************************************
154
LCInsertAfter()
155
*****************************************************************************/
156
157
void LCInsertAfter(listCollectionP listColl, int theAnchor, int theNewNode)
158
{
159
listColl->List[theNewNode].prev = theAnchor;
160
listColl->List[theNewNode].next = listColl->List[theAnchor].next;
161
listColl->List[listColl->List[theAnchor].next].prev = theNewNode;
162
listColl->List[theAnchor].next = theNewNode;
163
}
164
165
/*****************************************************************************
166
LCInsertBefore()
167
*****************************************************************************/
168
169
void LCInsertBefore(listCollectionP listColl, int theAnchor, int theNewNode)
170
{
171
LCPrepend(listColl, theAnchor, theNewNode);
172
}
173
174
#ifndef SPEED_MACROS
175
176
/*****************************************************************************
177
LCReset()
178
*****************************************************************************/
179
180
void LCReset(listCollectionP listColl)
181
{
182
int I;
183
184
for (I=0; I < listColl->N; I++)
185
listColl->List[I].prev = listColl->List[I].next = NIL;
186
}
187
188
/*****************************************************************************
189
LCCopy()
190
*****************************************************************************/
191
192
void LCCopy(listCollectionP dst, listCollectionP src)
193
{
194
int I;
195
196
if (dst==NULL || src==NULL || dst->N != src->N) return;
197
198
for (I=0; I<dst->N; I++)
199
dst->List[I] = src->List[I];
200
201
}
202
203
/*****************************************************************************
204
LCGetNext()
205
*****************************************************************************/
206
207
int LCGetNext(listCollectionP listColl, int theList, int theNode)
208
{
209
int next;
210
211
if (listColl==NULL || theList==NIL || theNode==NIL) return NIL;
212
next = listColl->List[theNode].next;
213
return next==theList ? NIL : next;
214
}
215
216
/*****************************************************************************
217
LCGetPrev()
218
*****************************************************************************/
219
220
int LCGetPrev(listCollectionP listColl, int theList, int theNode)
221
{
222
if (listColl==NULL || theList==NIL) return NIL;
223
if (theNode == NIL) return listColl->List[theList].prev;
224
if (theNode == theList) return NIL;
225
return listColl->List[theNode].prev;
226
}
227
228
/*****************************************************************************
229
LCPrepend()
230
*****************************************************************************/
231
232
int LCPrepend(listCollectionP listColl, int theList, int theNode)
233
{
234
/* If the append worked, then theNode is last, which in a circular
235
list is the direct predecessor of the list head node, so we
236
just back up one. For singletons, the result is unchanged. */
237
238
return listColl->List[LCAppend(listColl, theList, theNode)].prev;
239
}
240
241
/*****************************************************************************
242
LCAppend()
243
*****************************************************************************/
244
245
int LCAppend(listCollectionP listColl, int theList, int theNode)
246
{
247
/* If the given list is empty, then the given node becomes the
248
singleton list output */
249
250
if (theList == NIL)
251
{
252
listColl->List[theNode].prev = listColl->List[theNode].next = theNode;
253
theList = theNode;
254
}
255
256
/* Otherwise, make theNode the predecessor of head node of theList,
257
which is where the last node goes in a circular list. */
258
259
else
260
{
261
int pred = listColl->List[theList].prev;
262
263
listColl->List[theList].prev = theNode;
264
listColl->List[theNode].next = theList;
265
listColl->List[theNode].prev = pred;
266
listColl->List[pred].next = theNode;
267
}
268
269
/* Return the list (only really important if it was NIL) */
270
271
return theList;
272
}
273
274
/*****************************************************************************
275
LCDelete()
276
*****************************************************************************/
277
278
int LCDelete(listCollectionP listColl, int theList, int theNode)
279
{
280
/* If the list is a singleton, then NIL its pointers and
281
return NIL for theList*/
282
283
if (listColl->List[theList].next == theList)
284
{
285
listColl->List[theList].prev = listColl->List[theList].next = NIL;
286
theList = NIL;
287
}
288
289
/* Join predecessor and successor, dropping theNode from the list.
290
If theNode is the head of the list, then return the successor as
291
the new head node. */
292
293
else
294
{
295
int pred=listColl->List[theNode].prev,
296
succ=listColl->List[theNode].next;
297
298
listColl->List[pred].next = succ;
299
listColl->List[succ].prev = pred;
300
301
listColl->List[theNode].prev = listColl->List[theNode].next = NIL;
302
303
if (theList == theNode)
304
theList = succ;
305
}
306
307
return theList;
308
}
309
310
#endif // SPEED_MACROS
311
312