lib/dlist.c

Go to the documentation of this file.
00001 /* dlist.c - Doubly-linked list routines. 
00002  *
00003  * This file is copyright 2002 Jim Kent, but license is hereby
00004  * granted for all use - public, private or commercial. */
00005 #include "common.h"
00006 #include "dlist.h"
00007 
00008 static char const rcsid[] = "$Id: dlist.c,v 1.11 2005/07/04 18:44:09 markd Exp $";
00009 
00010 void dlListInit(struct dlList *dl)
00011 /* Initialize list to be empty */
00012 {
00013 dl->head = (struct dlNode *)(&dl->nullMiddle);
00014 dl->nullMiddle = NULL;
00015 dl->tail = (struct dlNode *)(&dl->head);
00016 }
00017 
00018 struct dlList *newDlList()
00019 /* Return a new doubly linked list. */
00020 {
00021 struct dlList *dl;
00022 AllocVar(dl);
00023 dl->head = (struct dlNode *)(&dl->nullMiddle);
00024 dl->tail = (struct dlNode *)(&dl->head);
00025 return dl;
00026 }
00027 
00028 void dlListReset(struct dlList *dl)
00029 /* Reset a list to the empty state (does not free values)  */
00030 {
00031 struct dlNode *node, *next;
00032 for (node = dl->head; node->next != NULL; node = next)
00033     {
00034     next = node->next;
00035     freeMem(node);
00036     }
00037 dl->head = (struct dlNode *)(&dl->nullMiddle);
00038 dl->nullMiddle = NULL;
00039 dl->tail = (struct dlNode *)(&dl->head);
00040 }
00041 
00042 void freeDlList(struct dlList **pList)
00043 /* Free up a doubly linked list and it's nodes (but not the node values). */
00044 {
00045 struct dlList *list = *pList;
00046 if (list != NULL)
00047     {
00048     dlListReset(list);
00049     freez(pList);
00050     }
00051 }
00052 
00053 void freeDlListAndVals(struct dlList **pList)
00054 /* Free all values in doubly linked list and the list itself.  (Just calls
00055  * freeMem on all values. */
00056 {
00057 struct dlList *list = *pList;
00058 if (list != NULL)
00059     {
00060     struct dlNode *node;
00061     for (node = list->head; node->next != NULL; node = node->next)
00062         freeMem(node->val);
00063     freeDlList(pList);
00064     }
00065 }
00066 
00067 
00068 void dlInsertBetween(struct dlNode *before, struct dlNode *after, struct dlNode *newNode)
00069 {
00070 before->next = newNode; 
00071 newNode->prev = before; 
00072 newNode->next = after;  
00073 after->prev = newNode; 
00074 }
00075 
00076 void dlAddBefore(struct dlNode *anchor, struct dlNode *newNode)
00077 /* Add a node to list before anchor member. */
00078 {
00079 dlInsertBetween(anchor->prev, anchor, newNode);
00080 }
00081 
00082 void dlAddAfter(struct dlNode *anchor, struct dlNode *newNode)
00083 /* Add a node to list after anchor member. */
00084 {
00085 dlInsertBetween(anchor, anchor->next, newNode);
00086 }
00087 
00088 void dlAddHead(struct dlList *list, struct dlNode *newNode)
00089 /* Add a node to head of list. */
00090 {
00091 struct dlNode *head = list->head;
00092 dlInsertBetween(head->prev, head, newNode);
00093 }
00094 
00095 void dlAddTail(struct dlList *list, struct dlNode *newNode)
00096 /* Add a node to tail of list. */
00097 {
00098 struct dlNode *tail = list->tail;
00099 dlInsertBetween(tail, tail->next, newNode);
00100 }
00101 
00102 struct dlNode *dlAddValBefore(struct dlNode *anchor, void *val)
00103 /* Create a node containing val and add to list before anchor member. */
00104 {
00105 struct dlNode *node = AllocA(struct dlNode);
00106 node->val = val;
00107 dlAddBefore(anchor, node);
00108 return node;
00109 }
00110 
00111 struct dlNode *dlAddValAfter(struct dlNode *anchor, void *val)
00112 /* Create a node containing val and add to list after anchor member. */
00113 {
00114 struct dlNode *node = AllocA(struct dlNode);
00115 node->val = val;
00116 dlAddAfter(anchor, node);
00117 return node;
00118 }
00119 
00120 struct dlNode *dlAddValHead(struct dlList *list, void *val)
00121 /* Create a node containing val and add to head of list. */
00122 {
00123 struct dlNode *node = AllocA(struct dlNode);
00124 node->val = val;
00125 dlAddHead(list, node);
00126 return node;
00127 }
00128 
00129 struct dlNode *dlAddValTail(struct dlList *list, void *val)
00130 /* Create a node containing val and add to tail of list. */
00131 {
00132 struct dlNode *node = AllocA(struct dlNode);
00133 node->val = val;
00134 dlAddTail(list, node);
00135 return node;
00136 }
00137 
00138 void dlRemove(struct dlNode *node)
00139 /* Removes a node from list. Node is not freed. */
00140 {
00141 struct dlNode *before = node->prev;
00142 struct dlNode *after = node->next;
00143 before->next = after;
00144 after->prev = before;
00145 node->prev = NULL;
00146 node->next = NULL;
00147 }
00148 
00149 void dlRemoveHead(struct dlList *list)
00150 /* Removes head from list. Node is not freed. */
00151 {
00152 dlRemove(list->head);
00153 }
00154 
00155 void dlRemoveTail(struct dlList *list)
00156 /* Remove tail from list. Node is not freed. */
00157 {
00158 dlRemove(list->tail);
00159 }
00160 
00161 struct dlNode *dlPopHead(struct dlList *list)
00162 /* Remove first node from list and return it. */
00163 {
00164 struct dlNode *node = list->head;
00165 if (node->next == NULL)
00166     return NULL;
00167 dlRemove(node);
00168 return node;
00169 }
00170 
00171 struct dlNode *dlPopTail(struct dlList *list)
00172 /* Remove last node from list and return it. */
00173 {
00174 struct dlNode *node = list->tail;
00175 if (node->prev == NULL)
00176     return NULL;
00177 dlRemove(node);
00178 return node;
00179 }
00180 
00181 void dlDelete(struct dlNode **nodePtr)
00182 /* Removes a node from list and frees it. */
00183 {
00184 struct dlNode *node = *nodePtr;
00185 if (node != NULL)
00186     {
00187     dlRemove(node);
00188     freeMem(node);
00189     }
00190 }
00191 
00192 int dlCount(struct dlList *list)
00193 /* Return length of list. */
00194 {
00195 return slCount(list->head) - 1;
00196 }
00197 
00198 
00199 struct dlSorter 
00200 /* Helper structure for sorting dlNodes preserving order */
00201     {
00202     struct dlNode *node;
00203     };
00204 
00205 static int (*compareFunc)(const void *elem1, const void *elem2);
00206 /* Node comparison pointer, just used by dlSortNodes and helpers. */
00207 
00208 static int dlNodeCmp(const void *elem1, const void *elem2)
00209 /* Compare two dlSorters indirectly, by calling compareFunc. */
00210 {
00211 struct dlSorter *a = (struct dlSorter *)elem1;
00212 struct dlSorter *b = (struct dlSorter *)elem2;
00213 return compareFunc(&a->node->val, &b->node->val);
00214 }
00215     
00216 void dlSort(struct dlList *list, 
00217         int (*compare )(const void *elem1,  const void *elem2))
00218 /* Sort a singly linked list with Qsort and a temporary array. 
00219  * The arguments to the compare function in real, non-void, life
00220  * are pointers to pointers of the type that is in the val field of 
00221  * the nodes of the list. */
00222 {
00223 int len = dlCount(list);
00224 
00225 if (len > 1)
00226     {
00227     /* Move val's onto an array, sort, and then put back into list. */
00228     struct dlSorter *sorter = needLargeMem(len * sizeof(sorter[0])), *s;
00229     struct dlNode *node;
00230     int i;
00231 
00232     for (i=0, node = list->head; i<len; ++i, node = node->next)
00233         {
00234         s = &sorter[i];
00235         s->node = node;
00236         }
00237     compareFunc = compare;
00238     qsort(sorter, len, sizeof(sorter[0]), dlNodeCmp);
00239     dlListInit(list);
00240     for (i=0; i<len; ++i)
00241         dlAddTail(list, sorter[i].node);
00242     freeMem(sorter);
00243     }
00244 }
00245 
00246 
00247 boolean dlEmpty(struct dlList *list)
00248 /* Return TRUE if list is empty. */
00249 {
00250 return dlIsEmpty(list);
00251 }
00252 
00253 struct dlNode *dlGetBeforeHead(struct dlList *list)
00254 /* Get the node before the head of the list */
00255 {
00256 if (dlEmpty(list))
00257     return list->head;
00258 else
00259     return list->head->prev;
00260 }
00261 
00262 struct dlNode *dlGetAfterTail(struct dlList *list)
00263 /* Get the node after the tail of the list */
00264 {
00265 if (dlEmpty(list))
00266     return list->tail;
00267 else
00268     return list->tail->next;
00269 }
00270 
00271 void *dlListToSlList(struct dlList *dList)
00272 /* Return slList from dlList. */
00273 {
00274 struct slList *list = NULL, *el;
00275 struct dlNode *node;
00276 
00277 for (node = dList->tail; node->prev != NULL; node = node->prev)
00278     {
00279     el = node->val;
00280     slAddHead(&list, el);
00281     }
00282 return list;
00283 }
00284 
00285 void dlCat(struct dlList *a, struct dlList *b)
00286 /* Move items from b to end of a. */
00287 {
00288 struct dlNode *node;
00289 while ((node = dlPopHead(b)) != NULL)
00290     dlAddTail(a, node);
00291 }
00292 
00293 struct dlNode *dlValInList(struct dlList *list, void *val)
00294 /* Return node on list if any that has associated val. */
00295 {
00296 struct dlNode *node;
00297 for (node = list->head; !dlEnd(node); node = node->next)
00298     if (node->val == val)
00299         return node;
00300 return NULL;
00301 }

Generated on Tue Dec 25 18:39:30 2007 for blat by  doxygen 1.5.2