|
|
1.1 root 1: // ************************************************************************
2: // LinkList.C - Ordered Double Linked List Package
3: // ************************************************************************
4: // PURPOSE: Provide a generalized sorted double linked list package
5: //
6: // FUNCTIONS:
7: // InitList - initialize/clear list
8: // CreateNode - allocate a new node that can be put into list
9: // InsertNode - insert a new node into the list
10: // DeleteCurrentNode - remove a node from the list
11: // GetNextNode - get the next (right) node from the CurrentNode
12: // GetPreviousNode - get the previous (left) node from the
13: // CurrentNode
14: // GetNode - get nth Occurence of a node that matches a
15: // key(s)
16: // GetListError - get the error value
17: //
18: // COMMENTS: The application must serialize access to the linked list
19: //
20: // Format of the Ordering and Matching functions is as follows:
21: //
22: // int OrderFunc( PNODE pNodeOne, PNODE pNodeTwo )
23: // {
24: // if( (pNodeOne->NodeData).Key < (pNodeTwo->NodeData).Key )
25: // return( LEFT_OF );
26: // if( (pNodeOne->NodeData).Key == (pNodeTwo->NodeData).Key )
27: // return( MATCH );
28: // if( (pNodeOne->NodeData).Key > (pNodeTwo->NodeData).Key )
29: // return( RIGHT_OF );
30: // }
31: //
32: // ************************************************************************
33: #include <StdLib.H> // malloc(), free()
34: #include <StdIO.H> // printf()
35: #include "LinkList.H"
36:
37: //-- NULL pointer dereferencing checking macro
38: #define CHECH_POINTER( Node ) \
39: if( Node == NULL ) { \
40: printf("Attempt to dereference NULL.\n"); \
41: return(pList->ListError = DEREFERENCE_NULL_ERROR); \
42: }
43:
44: //-- "member" functions that return the private data
45: int GetListError( PLIST pList ) { return( pList->ListError ); }
46: PNODE GetFirstNode( PLIST pList ) { return( pList->pFirstNode ); }
47: PNODE GetCurrentNode( PLIST pList ) { return( pList->pCurrentNode ); }
48: PNODE GetLastNode( PLIST pList ) { return( pList->pLastNode ); }
49:
50:
51: // ************************************************************************
52: // FUNCTION : InitList( PLIST pList, int (*)(PNODE, PNODE) )
53: // PURPOSE : initialize/clear list, registers the ordering function
54: // COMMENTS :
55: // ************************************************************************
56: int
57: InitList( PLIST pList, int (*OrderFunc)( PNODE pNodeOne, PNODE pNodeTwo ) )
58: {
59: PNODE pTempNode;
60:
61: //-- remove all nodes if the list is not empty
62: while( ( (pList->pFirstNode) != NULL) && ( (pList->ListError) == NO_ERROR_FOUND) ) {
63: pTempNode = (pList->pFirstNode);
64: if( DeleteCurrentNode( pList ) < NO_ERROR_FOUND ) {
65: (pList->ListError) = NO_NODE_ERROR;
66: return( pList->ListError );
67: }
68: }
69:
70: //-- initialize the "private" pointers to NULL
71: (pList->pFirstNode) = NULL;
72: (pList->pCurrentNode) = NULL;
73: (pList->pLastNode) = NULL;
74:
75: //-- register the link list data ordering function
76: (pList->OrderFunction) = OrderFunc;
77:
78: (pList->ListError) = NO_ERROR_FOUND;
79: return( pList->ListError );
80: }
81:
82:
83: // ************************************************************************
84: // FUNCTION : CreateNode( PLIST pList, PNODE* )
85: // PURPOSE : create/allocate a new node that can be put into list
86: // COMMENTS :
87: // ************************************************************************
88: int
89: CreateNode( PLIST pList, PNODE* ppNewNode )
90: {
91: (*ppNewNode) = (PNODE) malloc(sizeof(NODE));
92: if(*ppNewNode == NULL) {
93: printf("malloc failed.\n");
94: (pList->ListError) = NO_NODE_ERROR;
95: return( pList->ListError );
96: }
97: ((*ppNewNode)->pRightLink) = NULL;
98: ((*ppNewNode)->pLeftLink) = NULL;
99:
100: (pList->ListError) = NO_ERROR_FOUND;
101: return( pList->ListError );
102: }
103:
104:
105: // ************************************************************************
106: // FUNCTION : InsertNode( PLIST pList, PNODE )
107: // PURPOSE : insert a new node into the list
108: // COMMENTS : all nodes must have a unique key entry (from order
109: // function), if a match is found during an insert then the
110: // old node gets replaced with the new node
111: // NOTE: changes pList->pCurrentNode
112: // ************************************************************************
113: int
114: InsertNode( PLIST pList, PNODE pNewNode )
115: {
116: int Position;
117: int LastPosition;
118:
119: if( (pList->pFirstNode) == NULL ) {
120:
121: (pList->pFirstNode) = pNewNode;
122: (pList->pLastNode) = pNewNode;
123: (pList->pCurrentNode) = pNewNode;
124: (pList->ListError) = NO_ERROR_FOUND;
125:
126: return( pList->ListError );
127: }
128:
129: Position = (*(pList->OrderFunction))( pNewNode, pList->pCurrentNode );
130:
131: //-- search for insertion point
132: while( (pList->pCurrentNode) != NULL ) {
133:
134: LastPosition = Position;
135: Position = (*(pList->OrderFunction))(pNewNode, pList->pCurrentNode);
136:
137: if( (pList->pFirstNode) == (pList->pLastNode) )
138: break;
139:
140: if( Position != LastPosition )
141: break;
142:
143: if( (pList->pCurrentNode) == (pList->pFirstNode) ) {
144: if( Position == RIGHT_OF ) {
145: (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
146: continue;
147: }
148: break;
149: }
150:
151: if( (pList->pCurrentNode) == (pList->pLastNode) ) {
152: if( Position == LEFT_OF ) {
153: (pList->pCurrentNode) = ((pList->pCurrentNode)->pLeftLink);
154: continue;
155: }
156: break;
157: }
158:
159: if( Position == LastPosition ) {
160: if( Position == LEFT_OF) {
161: (pList->pCurrentNode) = ((pList->pCurrentNode)->pLeftLink);
162: continue;
163: }
164: if( Position == RIGHT_OF ) {
165: (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
166: continue;
167: }
168: break;
169: }
170:
171: }
172:
173: //-- now, insert the pNewNode
174: switch( Position ) {
175:
176: case LEFT_OF:
177: (pNewNode->pRightLink) = (pList->pCurrentNode);
178: (pNewNode->pLeftLink) = ((pList->pCurrentNode)->pLeftLink);
179: if( (pList->pCurrentNode) == (pList->pFirstNode) )
180: (pList->pFirstNode) = pNewNode;
181: else
182: (((pList->pCurrentNode)->pLeftLink)->pRightLink) = pNewNode;
183: ((pList->pCurrentNode)->pLeftLink) = pNewNode;
184: break;
185:
186: case RIGHT_OF:
187: (pNewNode->pLeftLink) = (pList->pCurrentNode);
188: (pNewNode->pRightLink) = ((pList->pCurrentNode)->pRightLink);
189: if( (pList->pCurrentNode) == (pList->pLastNode) )
190: (pList->pLastNode) = pNewNode;
191: else
192: (((pList->pCurrentNode)->pRightLink)->pLeftLink) = pNewNode;
193: ((pList->pCurrentNode)->pRightLink) = pNewNode;
194: break;
195:
196: case MATCH:
197: (pNewNode->pLeftLink) = ((pList->pCurrentNode)->pLeftLink);
198: (pNewNode->pRightLink) = ((pList->pCurrentNode)->pRightLink);
199: DestroyNode( pList->pCurrentNode );
200: break;
201:
202: }
203: (pList->pCurrentNode) = pNewNode;
204:
205: (pList->ListError) = NO_ERROR_FOUND;
206: return( pList->ListError );
207: }
208:
209:
210: // ************************************************************************
211: // FUNCTION : DestroyNode( PNODE )
212: // PURPOSE : deallocates a node
213: // COMMENTS :
214: // ************************************************************************
215: int
216: DestroyNode( PNODE pNode )
217: {
218: free( pNode );
219: return( 1 );
220: }
221:
222:
223: // ************************************************************************
224: // FUNCTION : DeleteCurrentNode( PLIST pList )
225: // PURPOSE : delete pList->pCurrentNode from the list and deallocate it
226: // COMMENTS : changes pList->pCurrentNode. Typically, GetNode is called first so
227: // pList->pCurrentNode points to the correct node
228: // ************************************************************************
229: int
230: DeleteCurrentNode( PLIST pList )
231: {
232: PNODE pOldCurrentNode;
233:
234: if( (pList->pCurrentNode) != NULL ) {
235: pOldCurrentNode = (pList->pCurrentNode);
236:
237: if( pOldCurrentNode == (pList->pFirstNode) ) {
238: (pList->pFirstNode) = (pOldCurrentNode->pRightLink);
239: (pList->pCurrentNode) = (pOldCurrentNode->pRightLink);
240: }
241: else {
242: ((pOldCurrentNode->pLeftLink)->pRightLink) = (pOldCurrentNode->pRightLink);
243: (pList->pCurrentNode) = (pOldCurrentNode->pLeftLink);
244: }
245:
246: if( pOldCurrentNode == (pList->pLastNode) )
247: (pList->pLastNode) = (pOldCurrentNode->pLeftLink);
248: else
249: ((pOldCurrentNode->pRightLink)->pLeftLink) = (pOldCurrentNode->pLeftLink);
250:
251: DestroyNode( pOldCurrentNode );
252:
253: (pList->ListError) = NO_ERROR_FOUND;
254: return( pList->ListError );
255: }
256:
257: (pList->ListError) = NO_ERROR_FOUND;
258: return( pList->ListError );
259: }
260:
261:
262: // ************************************************************************
263: // FUNCTION : GetNextNode( PLIST pList, PNODE* )
264: // PURPOSE : get the next (right) node from the pList->pCurrentNode
265: // COMMENTS : Does not change pList->pCurrentNode
266: // ************************************************************************
267: int
268: GetNextNode( PLIST pList, PNODE* ppNode )
269: {
270: CHECH_POINTER( ppNode );
271: if( ((*ppNode)->pRightLink) == NULL )
272: return( (pList->ListError) = NO_NEXT_NODE_ERROR );
273: (*ppNode) = ((*ppNode)->pRightLink);
274:
275: (pList->ListError) = NO_ERROR_FOUND;
276: return( pList->ListError );
277: }
278:
279:
280: // ************************************************************************
281: // FUNCTION : GetPreviousNode( PLIST pList, PNODE* )
282: // PURPOSE : get the previous (left) node from the pList->pCurrentNode
283: // COMMENTS : Does not change pList->pCurrentNode
284: // ************************************************************************
285: int
286: GetPreviousNode( PLIST pList, PNODE* ppNode )
287: {
288: CHECH_POINTER( ppNode );
289: if( ((*ppNode)->pLeftLink) == NULL )
290: return( (pList->ListError) = NO_PREV_NODE_ERROR);
291: (*ppNode) = ((*ppNode)->pLeftLink);
292:
293: (pList->ListError) = NO_ERROR_FOUND;
294: return( pList->ListError );
295: }
296:
297:
298: // ************************************************************************
299: // FUNCTION : GetNode( PLIST pList, PNODE*, int (*)(PNODE, PNODE), int )
300: // PURPOSE : get nth Occurence of a node from the list that matches a
301: // key(s).
302: // COMMENTS : may use the ordering function or a new matching function
303: // if not searching for a match based on the primary
304: // ordering key. Note: the matching and ordering functions
305: // have the same definition.
306: // NOTE: changes pList->pCurrentNode
307: // ************************************************************************
308: int
309: GetNode( PLIST pList, PNODE* ppKeyNode,
310: int (*MatchFunction)( PNODE pNodeOne, PNODE pNodeTwo ),
311: int Occurence )
312: {
313: int Position;
314:
315: //-- if match and order are same function
316: if( MatchFunction == (pList->OrderFunction) ) {
317: int LastPosition;
318:
319: Position = (*MatchFunction)(*ppKeyNode, pList->pCurrentNode);
320: LastPosition = Position;
321:
322: while( Occurence ) {
323: if( (Position == LEFT_OF) && (LastPosition == LEFT_OF)
324: && ( (pList->pCurrentNode) != (pList->pFirstNode) ) )
325: (pList->pCurrentNode) = ((pList->pCurrentNode)->pLeftLink);
326: else if( (Position == RIGHT_OF) && (LastPosition == RIGHT_OF)
327: && ( (pList->pCurrentNode) != (pList->pLastNode) ) )
328: (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
329: else {
330: Occurence--;
331: continue;
332: }
333: LastPosition = Position;
334: Position = (*MatchFunction)(*ppKeyNode, pList->pCurrentNode);
335: }
336:
337: }
338: else { // match and order are not the same function, thus start
339: // the search at the front of the list
340: (pList->pCurrentNode) = (pList->pFirstNode);
341:
342: while( (Occurence > 0) && ( (pList->pCurrentNode) != NULL)) {
343: Position = (*MatchFunction)(*ppKeyNode, pList->pCurrentNode);
344: if(Position == MATCH)
345: Occurence--;
346: if(Occurence > 0 )
347: (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
348: }
349:
350: }
351:
352: if( (Position == MATCH) && (Occurence == 0) ) {
353: *ppKeyNode = (pList->pCurrentNode);
354:
355: (pList->ListError) = NO_ERROR_FOUND;
356: return( pList->ListError );
357: }
358:
359: (pList->ListError) = NO_MATCH_ERROR;
360: return( pList->ListError );
361: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.