Initial revision
This commit is contained in:
+209
@@ -0,0 +1,209 @@
|
||||
#ifndef LL_H
|
||||
#define LL_H
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Linked Lists! (Doubly-Linked Lists)
|
||||
*******************************************************************
|
||||
|
||||
To create a list, do the following:
|
||||
|
||||
LL *list;
|
||||
list = LL_new();
|
||||
if(!list) handle_an_error();
|
||||
|
||||
The list can hold any type of data. You will need to typecast your
|
||||
datatype to a "void *", though. So, to add something to the list,
|
||||
the following would be a good way to start:
|
||||
|
||||
typedef struct my_data {
|
||||
char string[16];
|
||||
int number;
|
||||
} my_data;
|
||||
|
||||
my_data *thingie;
|
||||
|
||||
for(something to something else)
|
||||
{
|
||||
thingie = malloc(sizeof(my_data));
|
||||
LL_AddNode(list, (void *)thingie); // typecast it to a "void *"
|
||||
}
|
||||
|
||||
For errors, the general convention is that "0" means success, and
|
||||
a negative number means failure. Check LL.c to be sure, though.
|
||||
|
||||
*******************************************************************
|
||||
|
||||
To change the data, try this:
|
||||
|
||||
thingie = (my_data *)LL_Get(list); // typecast it back to "my_data"
|
||||
thingie->number = another_number;
|
||||
|
||||
You don't need to "Put" the data back, but it doesn't hurt anything.
|
||||
|
||||
LL_Put(list, (void *)thingie);
|
||||
|
||||
However, if you want to point the node's data somewhere else, you'll
|
||||
need to get the current data first, keep track of it, then set the data
|
||||
to a new location:
|
||||
|
||||
my_data * old_thingie, new_thingie;
|
||||
|
||||
old_thingie = (my_data *)LL_Get(list);
|
||||
LL_Put(list, (void *)new_thingie);
|
||||
|
||||
// Now, do something with old_thingie. (maybe, free it?)
|
||||
|
||||
Or, you could just delete the node entirely and then add a new one:
|
||||
|
||||
my_data * thingie;
|
||||
|
||||
thingie = (my_data *)LL_DeleteNode(list);
|
||||
free(thingie);
|
||||
|
||||
thingie->number = 666;
|
||||
|
||||
LL_InsertNode(list, (void *)thingie);
|
||||
|
||||
*******************************************************************
|
||||
|
||||
To operate on each list item, try this:
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
my_data = (my_data *)LL_Get(list);
|
||||
... do something to it ...
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
*******************************************************************
|
||||
|
||||
You can also treat the list like a stack, or a queue. Just use the
|
||||
following functions:
|
||||
|
||||
LL_Push() // Regular stack stuff: add, remove, peek, rotate
|
||||
LL_Pop()
|
||||
LL_Top()
|
||||
LL_Roll()
|
||||
|
||||
LL_Shift() // Other end of the stack (like in perl)
|
||||
LL_Unshift()
|
||||
LL_Look()
|
||||
LL_UnRoll()
|
||||
|
||||
LL_Enqueue() // Standard queue operations
|
||||
LL_Dequeue()
|
||||
|
||||
There are also other goodies, like sorting and searching.
|
||||
|
||||
*******************************************************************
|
||||
|
||||
Array-like operations will come later, to allow numerical indexing:
|
||||
|
||||
LL_nGet(list, 3);
|
||||
LL_nSwap(list, 6, 13);
|
||||
LL_nPut(list, -4, data); // Puts item at 4th place from the end..
|
||||
|
||||
More ideas for later:
|
||||
|
||||
LL_MoveNode(list, amount); // Slides a node to another spot in the list
|
||||
-- LL_MoveNode(list, -1); // moves a node back one toward the head
|
||||
|
||||
... um, more?
|
||||
|
||||
*******************************************************************
|
||||
That's about it, for now... Be sure to free the list when you're done!
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
// See LL.c for more detailed descriptions of these functions.
|
||||
|
||||
typedef struct LL_node
|
||||
{
|
||||
struct LL_node *next, *prev;
|
||||
void *data;
|
||||
} LL_node;
|
||||
|
||||
typedef struct LL
|
||||
{
|
||||
LL_node head, tail;
|
||||
LL_node *current;
|
||||
} LL;
|
||||
|
||||
|
||||
|
||||
// Creates a new list...
|
||||
LL * LL_new();
|
||||
// Destroying lists...
|
||||
int LL_Destroy(LL *list);
|
||||
int LL_node_Destroy(LL_node *node);
|
||||
int LL_node_Unlink(LL_node *node);
|
||||
int LL_node_DestroyData(LL_node *node);
|
||||
|
||||
// Returns to the beginning of the list...
|
||||
int LL_Rewind(LL *list);
|
||||
// Goes to the end of the list...
|
||||
int LL_End(LL *list);
|
||||
// Go to the next node
|
||||
int LL_Next(LL *list);
|
||||
// Go to the previous node
|
||||
int LL_Prev(LL *list);
|
||||
|
||||
// Data manipulation
|
||||
void * LL_Get(LL *list);
|
||||
int LL_Put(LL *list, void *data);
|
||||
// Don't use these next two unless you really know what you're doing.
|
||||
LL_node * LL_GetNode(LL *list);
|
||||
int LL_PutNode(LL *list, LL_node *node);
|
||||
|
||||
void * LL_GetFirst(LL *list); // gets data from first node
|
||||
void * LL_GetNext (LL *list); // ... next node
|
||||
void * LL_GetPrev (LL *list); // ... prev node
|
||||
void * LL_GetLast (LL *list); // ... last node
|
||||
|
||||
int LL_AddNode(LL *list, void * add); // Adds node AFTER current one
|
||||
int LL_InsertNode(LL *list, void * add);// Adds node BEFORE current one
|
||||
// Removes a node from the link; returns the data from the node
|
||||
void * LL_DeleteNode(LL *list);
|
||||
// Removes a specific node...
|
||||
void * LL_Remove(LL *list, void * data);
|
||||
|
||||
// Stack operations
|
||||
int LL_Push(LL *list, void *add); // Add node to end of list
|
||||
void * LL_Pop(LL *list); // Remove node from end of list
|
||||
void * LL_Top(LL *list); // Peek at end node
|
||||
void * LL_Shift(LL *list); // Remove node from start of list
|
||||
void * LL_Look(LL *list); // Peek at first node
|
||||
int LL_Unshift(LL *list, void *add); // Add node to beginning of list
|
||||
|
||||
int LL_Roll(LL *list); // Make first node last
|
||||
int LL_UnRoll(LL *list);// Roll the other way...
|
||||
|
||||
// Queue operations...
|
||||
//int LL_Enqueue(LL *list, void *add);
|
||||
//void * LL_Dequeue(LL *list);
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Queue operations...
|
||||
#define LL_Enqueue(list,add) LL_Push(list,add)
|
||||
|
||||
#define LL_Dequeue(list) LL_Shift(list)
|
||||
|
||||
int LL_PriorityEnqueue(LL *list, void *add, int compare(void *, void *));
|
||||
|
||||
|
||||
int LL_SwapNodes(LL_node *one, LL_node *two); // Switch two nodes positions...
|
||||
int LL_nSwapNodes(int one, int two); // Switch two nodes positions...
|
||||
|
||||
int LL_Length(LL *list); // Returns # of nodes in entire list
|
||||
|
||||
// Searching...
|
||||
void * LL_Find(LL *list, int compare(void *, void *), void *value);
|
||||
|
||||
// Sorts the list...
|
||||
int LL_Sort(LL *list, int compare(void *, void *));
|
||||
|
||||
|
||||
// Debugging...
|
||||
void LL_dprint(LL *list);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user