/*1Planarity-Related Graph Algorithms Project2Copyright (c) 1997-2010, John M. Boyer3All rights reserved. Includes a reference implementation of the following:45* John M. Boyer. "Simplified O(n) Algorithms for Planar Graph Embedding,6Kuratowski Subgraph Isolation, and Related Problems". Ph.D. Dissertation,7University of Victoria, 2001.89* John M. Boyer and Wendy J. Myrvold. "On the Cutting Edge: Simplified O(n)10Planarity by Edge Addition". Journal of Graph Algorithms and Applications,11Vol. 8, No. 3, pp. 241-273, 2004.1213* John M. Boyer. "A New Method for Efficiently Generating Planar Graph14Visibility Representations". In P. Eades and P. Healy, editors,15Proceedings of the 13th International Conference on Graph Drawing 2005,16Lecture Notes Comput. Sci., Volume 3843, pp. 508-511, Springer-Verlag, 2006.1718Redistribution and use in source and binary forms, with or without modification,19are permitted provided that the following conditions are met:2021* Redistributions of source code must retain the above copyright notice, this22list of conditions and the following disclaimer.2324* Redistributions in binary form must reproduce the above copyright notice, this25list of conditions and the following disclaimer in the documentation and/or26other materials provided with the distribution.2728* Neither the name of the Planarity-Related Graph Algorithms Project nor the names29of its contributors may be used to endorse or promote products derived from this30software without specific prior written permission.3132THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"33AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE34IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE35DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR36ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES37(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;38LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON39ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT40(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS41SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.42*/4344#define _LISTCOLL_C4546#include "appconst.h"47#include "listcoll.h"48#include <stdlib.h>4950/*****************************************************************************51The data structure defined by this module manages a set of N objects52arranged as a collection of circular lists, each containing distinct53elements from the set.5455On construction, LCNew() creates an array of N nodes, each containing a56prev and next pointer. The identity of the node is given by its array index.57Each node's prev and next pointers are set to NIL, indicating that the node58is not currently part of a list. LCReset() can be called to reset all59pointers to NIL.6061The function LCFree() deallocates the collection of lists and clears the62pointer variable used to pass the collection.6364An empty list is indicated by NIL. To begin a list with node I, call65LCPrepend() or LCAppend() with the NIL list and with I as the node. The prev66and next pointers in node I are set to I and I is returned as the head of67the list.6869Future calls to LCPrepend() add a node J as the new first element of the list,70so the list given as input is pointed to by J's next, and J is returned as71the head of the list.7273Future calls to LCAppend() add a node J as the new last element, so the prev74pointer of the list given as input will indicate node J, and the input list75is returned as the head of the list.7677LCInsertAfter() adds a node immediately after a given anchor node.7879LCInsertBefore() adds a node immediately before a given anchor node and has80the same effect on a list as LCPrepend().8182The function LCDelete() removes a node I from a list L. If node I is in the83list alone, then its pointers are set to NIL, and NIL is returned as the list.84If node I is not alone in the list, but it is the head of the list (in other85words, I is equal to L), then L's sucessor is returned as the new head of the86list. Whether or not I equals L, node I is deleted by joining its predecessor87and successor nodes.8889LCCopy() copies the contents of one collection to another if both are of90equal size.9192LCGetNext() is used for forward iteration through a list in the collection.93The expected iteration pattern is first to process the node one has, then call94LCGetNext() to get the next node, so if the result of LCGetNext() would be the95head of the list, then NIL is returned instead. This simplifies most96coding operations involving LCGetNext().9798LCGetPrev() is used for backward iteration through a list in the collection.99The expected iteration pattern is that the last list element will be obtained100by an initial call to LCGetPrev() with theNode equal to NIL. This call101should appear outside of the iteration loop. The iteration loop then102proceeds while the current node is not NIL. The loop body processes the103current node, then LCGetPrev() is called with theNode equal to the current104node. LCGetPrev() returns NIL if theNode is equal to theList. Otherwise,105the predecessor of theNode is returned.106107*****************************************************************************/108109/*****************************************************************************110LCNew()111*****************************************************************************/112113listCollectionP LCNew(int N)114{115listCollectionP theListColl = NULL;116117if (N <= 0) return theListColl;118119theListColl = (listCollectionP) malloc(sizeof(listCollectionRec));120if (theListColl != NULL)121{122theListColl->List = (lcnode *) malloc(N*sizeof(lcnode));123if (theListColl->List == NULL)124{125free(theListColl);126theListColl = NULL;127}128else129{130theListColl->N = N;131LCReset(theListColl);132}133}134return theListColl;135}136137/*****************************************************************************138LCFree()139*****************************************************************************/140141void LCFree(listCollectionP *pListColl)142{143if (pListColl==NULL || *pListColl==NULL) return;144145if ((*pListColl)->List != NULL)146free((*pListColl)->List);147148free(*pListColl);149*pListColl = NULL;150}151152/*****************************************************************************153LCInsertAfter()154*****************************************************************************/155156void LCInsertAfter(listCollectionP listColl, int theAnchor, int theNewNode)157{158listColl->List[theNewNode].prev = theAnchor;159listColl->List[theNewNode].next = listColl->List[theAnchor].next;160listColl->List[listColl->List[theAnchor].next].prev = theNewNode;161listColl->List[theAnchor].next = theNewNode;162}163164/*****************************************************************************165LCInsertBefore()166*****************************************************************************/167168void LCInsertBefore(listCollectionP listColl, int theAnchor, int theNewNode)169{170LCPrepend(listColl, theAnchor, theNewNode);171}172173#ifndef SPEED_MACROS174175/*****************************************************************************176LCReset()177*****************************************************************************/178179void LCReset(listCollectionP listColl)180{181int I;182183for (I=0; I < listColl->N; I++)184listColl->List[I].prev = listColl->List[I].next = NIL;185}186187/*****************************************************************************188LCCopy()189*****************************************************************************/190191void LCCopy(listCollectionP dst, listCollectionP src)192{193int I;194195if (dst==NULL || src==NULL || dst->N != src->N) return;196197for (I=0; I<dst->N; I++)198dst->List[I] = src->List[I];199200}201202/*****************************************************************************203LCGetNext()204*****************************************************************************/205206int LCGetNext(listCollectionP listColl, int theList, int theNode)207{208int next;209210if (listColl==NULL || theList==NIL || theNode==NIL) return NIL;211next = listColl->List[theNode].next;212return next==theList ? NIL : next;213}214215/*****************************************************************************216LCGetPrev()217*****************************************************************************/218219int LCGetPrev(listCollectionP listColl, int theList, int theNode)220{221if (listColl==NULL || theList==NIL) return NIL;222if (theNode == NIL) return listColl->List[theList].prev;223if (theNode == theList) return NIL;224return listColl->List[theNode].prev;225}226227/*****************************************************************************228LCPrepend()229*****************************************************************************/230231int LCPrepend(listCollectionP listColl, int theList, int theNode)232{233/* If the append worked, then theNode is last, which in a circular234list is the direct predecessor of the list head node, so we235just back up one. For singletons, the result is unchanged. */236237return listColl->List[LCAppend(listColl, theList, theNode)].prev;238}239240/*****************************************************************************241LCAppend()242*****************************************************************************/243244int LCAppend(listCollectionP listColl, int theList, int theNode)245{246/* If the given list is empty, then the given node becomes the247singleton list output */248249if (theList == NIL)250{251listColl->List[theNode].prev = listColl->List[theNode].next = theNode;252theList = theNode;253}254255/* Otherwise, make theNode the predecessor of head node of theList,256which is where the last node goes in a circular list. */257258else259{260int pred = listColl->List[theList].prev;261262listColl->List[theList].prev = theNode;263listColl->List[theNode].next = theList;264listColl->List[theNode].prev = pred;265listColl->List[pred].next = theNode;266}267268/* Return the list (only really important if it was NIL) */269270return theList;271}272273/*****************************************************************************274LCDelete()275*****************************************************************************/276277int LCDelete(listCollectionP listColl, int theList, int theNode)278{279/* If the list is a singleton, then NIL its pointers and280return NIL for theList*/281282if (listColl->List[theList].next == theList)283{284listColl->List[theList].prev = listColl->List[theList].next = NIL;285theList = NIL;286}287288/* Join predecessor and successor, dropping theNode from the list.289If theNode is the head of the list, then return the successor as290the new head node. */291292else293{294int pred=listColl->List[theNode].prev,295succ=listColl->List[theNode].next;296297listColl->List[pred].next = succ;298listColl->List[succ].prev = pred;299300listColl->List[theNode].prev = listColl->List[theNode].next = NIL;301302if (theList == theNode)303theList = succ;304}305306return theList;307}308309#endif // SPEED_MACROS310311312