source: npl/mediabox/lcdproc_edwin/src/old/llistd.c

Last change on this file was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 9 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 15.7 KB
Line 
1#include <stdio.h>      // for NULL definition
2#include "llistd.h"     // function prototypes
3
4/*****************************************************************************
5* AUTHOR: Scott Scriven, SSN: 523-21-9640, CLASS: CS151.003, DATE: 96-11-21
6******************************************************************************
7* Doubly Linked Lists!  (some of my really old code, commented for this class)
8*  This code will handle "generic" Doubly-Linked Lists.  These lists can be
9*  any type as long as they satisfy a few requirements:
10*       Your structure must start with two integer pointers:
11*               struct mystruct {
12*                 int *next, *prev;
13*                 ...
14*               };
15*       That's all, pretty much.
16*
17*  Most of the functions take integer pointers.  This means you will have to
18*  call them in one of the following ways:
19*       function((int *)&mystruct);
20*       function((int *)mystruct);
21*       function(&mystruct.next);
22*
23******************************************************************************
24*  If I'm not mistaken, this code should work regardless of your machine's
25*  integer size (16/32/64/etc... bit)
26******************************************************************************
27* Note that we have to do NULL checking to make sure we don't try to write
28* to protected areas of memory if we reach the beginning/end of a list.
29*
30* We also do some circular-link checking to avoid infinite loops.
31*       These loops will work fine:
32*               a <-> b <-> c <-> a <-> b...
33*               a <-> b <-> c -> c -> c...
34*       This loop might make this code puke:
35*               a <-> b <-> c <-> d -> c    d <- e <-> f <-> g
36*****************************************************************************/
37
38
39/*****************************************************************************
40* Function:  LLMakeFirstNode()
41******************************************************************************
42* Description:
43*  Makes a node stand alone; creates the first node of a list.  You must do
44*  the memory/node allocation manually.  It returns the parameter you send it.
45******************************************************************************
46* Function Calls:
47*  None.
48*****************************************************************************/
49int * LLMakeFirstNode(int * first)      // Make a standalone node...
50{
51  (int *)first[0] = NULL;
52  (int *)first[1] = NULL;
53  return first;
54}
55
56
57/*****************************************************************************
58* Function:  LLFindFirst()
59******************************************************************************
60* Description:
61*  Given a node of a list, it returns the first node of the list (assuming
62*  that the first node either points to NULL or itself).  If list is circular,
63*  it returns *next* node in the list.
64******************************************************************************
65* Function Calls:
66*  LLFindPrev           See below...
67*****************************************************************************/
68int * LLFindFirst(int * current)        // returns address of First node
69{
70  int *prev=current;
71
72  // If prev[1] (pointer to previous node) is NULL, we hit the beginning.
73  // If prev[1] is the same as current, we've got a circular linked list...
74  while((int *)prev[1] != NULL  && (int *)prev[1] != current)
75  {
76    prev = LLFindPrev(prev);
77  }
78 
79  return prev;
80}
81
82/*****************************************************************************
83* Function:  LLFindNext()
84******************************************************************************
85* Description:
86*  Returns the address of the next node in the list, or NULL if we're at the
87*  end of the list.
88******************************************************************************
89* Function Calls:
90*  None.
91*****************************************************************************/
92int * LLFindNext(int * current)         // returns address of next node
93{
94  // Return the address of the next node
95  if((int *)current[0] != current)
96    return (int *)current[0];
97  else
98    return NULL;
99}
100
101/*****************************************************************************
102* Function:  LLFindPrev()
103******************************************************************************
104* Description:
105*  Returns the address of the previous node in the list, or NULL if we're
106*  at the beginning of the list.
107******************************************************************************
108* Function Calls:
109*  None.
110*****************************************************************************/
111int * LLFindPrev(int * current)         // returns address of prev node
112{
113  // Return the address of the previous node
114  if((int *)current[1] != current)   
115    return (int *)current[1];
116  else
117    return NULL;
118}
119
120/*****************************************************************************
121* Function:  LLFindLast()
122******************************************************************************
123* Description:
124*  Given any node, returns the address of the last node of that list.  This
125*  works just like LLFindFirst(), but in reverse.
126******************************************************************************
127* Function Calls:
128*  LLFindNext           See above...
129*****************************************************************************/
130int * LLFindLast(int * current)         // returns address of last node
131{
132  int *next = current;
133 
134  // If next[0] (pointer to next node) is NULL, we hit the end.
135  // If next[0] is the same as current, we've got a circular linked list...
136  while((int *)next[0] != NULL  &&  (int *)next[0] != current)
137  {
138    next = LLFindNext(next);
139  }
140 
141  return next;
142}
143
144
145/*****************************************************************************
146* Function:  LLAddNode()
147******************************************************************************
148* Description:
149*  Inserts a node in the list *after* the "current" node.  It updates the
150*  list neighbors accordingly.
151******************************************************************************
152* Function Calls:
153*  LLFindNext           See above...
154*****************************************************************************/
155int * LLAddNode(int * current, int * add)       // Adds node AFTER current one
156{
157  int *next;
158 
159  if(current == add) return current;    // We can't add a node to itself...
160 
161  next = LLFindNext(current);   // Get the next node address
162
163  (int *)current[0] = add;      // Point the current node to the new node
164  (int *)add[0] = next;         // Point the new node to next node
165  (int *)add[1] = current;      // Make new node point back to the current node
166
167  if(next != NULL)
168    (int *)next[1] = add;       // Point next node back to the new node
169 
170  return add;           // Return the address of the new node
171}
172
173/*****************************************************************************
174* Function:  LLInsertNode()
175******************************************************************************
176* Description:
177*  Inserts a node in the list *before* the "current" node.  It updates the
178*  list neighbors accordingly.
179******************************************************************************
180* Function Calls:
181*  LLFindPrev           See above...
182*****************************************************************************/
183int * LLInsertNode(int * current, int * add)    // Adds node BEFORE current one
184{
185  int *prev;
186 
187  if(current == add) return current;    // We can't add a node to itself...
188
189  prev = LLFindPrev(current);   // Get the previous node's address
190 
191  if(prev != NULL)
192    (int *)prev[0] = add;       // Previous node points to new node
193  (int *)add[0] = current;      // New node points to current node
194  (int *)add[1] = prev;         // New node points back to previous node
195  (int *)current[1] = add;      // Current node points back to new node
196 
197  return add;           // Return the address of the new node
198}
199
200/*****************************************************************************
201* Function:  LLCutNode()
202******************************************************************************
203* Description:
204*  Removes a node from the list, and joins its neighbors.  Returns the
205*  address of the cut node.  You must deallocate the node manually, if
206*  you want to free its memory.
207******************************************************************************
208* Function Calls:
209*  LLFindPrev           See Above...
210*  LLFindNext           See Above...
211*****************************************************************************/
212int * LLCutNode(int * cut)                      // Removes a node from the link
213{
214  int * prev, * next;
215 
216  prev = LLFindPrev(cut);       // Find surrounding nodes...
217  next = LLFindNext(cut);
218
219  (int *)cut[0] = NULL;         // Make the removed node point nowhere
220  (int *)cut[1] = NULL;
221 
222  if(prev != NULL)              // Join the surrounding nodes... 
223    (int *)prev[0] = next;
224  if(next != NULL)
225    (int *)next[1] = prev;
226 
227  return cut;           // Return the address of the node that has been cut...
228}
229
230
231/*****************************************************************************
232* Function:  LLPush()
233******************************************************************************
234* Description:
235*  Inserts a node at the end of the whole list.  "Current" can be any node
236*  in the list, and "add" is the node you want to add.
237******************************************************************************
238* Function Calls:
239*  LLFindLast()         See above...
240*  LLAddNode()          See above...
241*****************************************************************************/
242int * LLPush(int * current, int * add)     // Add node to end of list
243{
244  int *last;
245 
246  last = LLFindLast(current);
247 
248  return LLAddNode(last, add);
249}
250
251/*****************************************************************************
252* Function:  LLPop()
253******************************************************************************
254* Description:
255*  Pops (removes) a node off the end of the list.  Returns the address of
256*  the node we chopped off.  "current" can be any node in the list.
257******************************************************************************
258* Function Calls:
259*  LLFindLast           See above...
260*  LLCutNode            See above...
261*****************************************************************************/
262int * LLPop(int * current)                 // Remove node from end of list
263{
264  int *last;
265 
266  last = LLFindLast(current);
267 
268  return LLCutNode(last);
269}
270
271/*****************************************************************************
272* Function:  LLShift()
273******************************************************************************
274* Description:
275*  Pops (removes) a node from the beginning of the list.  Returns the address
276*  of the node we cut off.
277******************************************************************************
278* Function Calls:
279*  LLFindFirst          See above...
280*  LLCutNode            See above...
281*****************************************************************************/
282int * LLShift(int * current)               // Remove node from start of list
283{
284  int *begin;
285 
286  begin = LLFindFirst(current);
287 
288  return LLCutNode(begin);
289}
290
291/*****************************************************************************
292* Function:  LLUnshift()
293******************************************************************************
294* Description:
295*  Inserts a node at the beginning of the list.
296******************************************************************************
297* Function Calls:
298*  LLFindFirst          See above...
299*  LLInsertNode         See above...
300*****************************************************************************/
301int * LLUnshift(int * current, int * add) // Add node to beginning of list
302{
303  int *begin;
304 
305  begin = LLFindFirst(current);
306 
307  return LLInsertNode(begin, add);
308}
309
310/*****************************************************************************
311* Function:  LLSwapNodes()
312******************************************************************************
313* Description:
314*  Switches two nodes' positions in the linked list.  It can handle cases
315*  when the nodes are complete seperate, cases when the nodes are each
316*  other's neighbors, and cases when the two nodes are the same one.
317*  No return value.
318******************************************************************************
319* Function Calls:
320*  LLFindNext           See Above...
321*  LLFindPrev           See above...
322*****************************************************************************/
323void  LLSwapNodes(int * one, int * two)   // Switch two nodes' positions...
324{
325  int *firstprev, *firstnext;
326  int *secondprev, *secondnext;
327 
328  if(one == two) return;        // if they're the same, do nothing
329 
330  firstprev  = LLFindPrev(one); // Store the addresses of their neighbors...
331  firstnext  = LLFindNext(one);
332  secondprev = LLFindPrev(two);
333  secondnext = LLFindNext(two);
334 
335  if(firstprev  != NULL)  (int *)firstprev[0] = two;    // Swap their
336  if(firstnext  != NULL)  (int *)firstnext[1] = two;    // Neighbors' pointers
337  if(secondprev != NULL)  (int *)secondprev[0] = one;
338  if(secondnext != NULL)  (int *)secondnext[1] = one;
339 
340  (int *)one[0] = secondnext;   // Swap the two nodes' pointers
341  (int *)one[1] = secondprev;
342  (int *)two[0] = firstnext;
343  (int *)two[1] = firstprev;
344 
345  if(firstnext  == two) (int *)one[1] = two;    // Fix things if they were
346  if(firstprev  == two) (int *)one[0] = two;    // next to each other...
347  if(secondprev == one) (int *)two[0] = one;
348  if(secondnext == one) (int *)two[1] = one;
349}
350
351/*****************************************************************************
352* Function:  LLCountNodes()
353******************************************************************************
354* Description:
355*  Traverses the entire list and returns the number of nodes it finds.
356******************************************************************************
357* Function Calls:
358*  LLFindFirst          See above...
359*  LLFindNext           See above...
360*****************************************************************************/
361int   LLCountNodes(int * current)       // Returns # of nodes in entire list
362{
363  int numnodes=1;
364  int *first, *next;
365 
366  first = LLFindFirst(current);         // Get the first node...
367  next = first;
368 
369
370  // If next[0] (pointer to next node) is NULL, we hit the end.
371  // If next[0] is the same as current, we've got a circular linked list...
372  while((int *)next[0] != NULL  &&  (int *)next[0] != first)
373  {
374    numnodes++;
375    next = LLFindNext(next);
376  }
377 
378  return numnodes;
379}
380
381
382/*****************************************************************************
383* Function:  LLSelectSort()
384******************************************************************************
385* Description:
386*  Given any node in a list, sorts the whole list using a selection sort
387*  algorithm.  You must supply a function to compare two nodes.  The
388*  return value is the address of the new first node in the list.
389******************************************************************************
390* Function Calls:
391*  LLCountNodes         See above...
392*  LLFindLast           See above...
393*  LLFindFirst          See above...
394*  LLFindNext           See above...
395*  LLFindPrev           See above...
396*  LLSwapNodes          See above...
397*  compare              The user-defined function which compares two nodes.
398*                       If you've ever used qsort, this should be familiar.
399*****************************************************************************/
400// Sorts the list and returns a pointer to the first node
401int * LLSelectSort(int * current, int compare(void *, void *))
402{
403  int i,j;              // Junk / loop variables
404  int numnodes;         // number of nodes in list
405  int *best, *last;     // best match and last node in the list
406 
407  numnodes = LLCountNodes(current);     // get the number of nodes...
408  last = LLFindLast(current);           // Find the last node.
409 
410  for(i=numnodes-1; i>1; i--)
411  {
412    current = LLFindFirst(current);     // get the first node again
413    best = last;                        // reset our "best" node
414   
415    for(j=0; j<i; j++)
416    {
417      if(compare(current, best) > 0)    // If we found a better match...
418      {
419        best = current;                 // keep track of the "best" match
420      }
421      current = LLFindNext(current);    // Go to the next node.
422    }
423
424    LLSwapNodes(last, best);            // Switch two nodes...
425    last = LLFindPrev(best);            // And go backwards by one node.
426  }
427 
428  return LLFindFirst(current);          // return pointer to the first node.
429}
Note: See TracBrowser for help on using the repository browser.