NOOB here.

√searched archives
√searched faqs
√googles
√tutorials

I'm attempting to learn about generic linked lists from Kendall Bennett's CTools10 which I'll include below for reference.

my question is this: He defines a bucket but never any variables to store the data. How do I assign data to the bucket if the only variable in the bucket is *next?

Is there an example. of use of this library.




I know I'm in a different world now. I'm trying to turn off my old brain but it's really hard to believe I might have to re-impliment the code for an array every time I want an array of undefined length. Whew. sorry for the ..........fest.



Code:
typedef struct LST_BUCKET {

	struct LST_BUCKET	*next;

	} LST_BUCKET;



//header
Code:
/****************************************************************************

*

*					Copyright (C) 1991 Kendall Bennett.

*							All rights reserved.

*

* Filename:		$RCSfile: list.h $

* Version:		$Revision: 1.7 $

*

* Language:		ANSI C

* Environment:	any

*

* Description:	Header file for linked list routines.

*

* $Id: list.h 1.7 91/12/31 19:41:16 kjb Exp $

*

* Revision History:

* -----------------

*

* $Log:	list.h $

* Revision 1.7  91/12/31  19:41:16  kjb

* 

* Modified include files directories.

* 

* Revision 1.6  91/09/27  03:11:04  kjb

* Added compatibility with C++.

* 

* Revision 1.5  91/09/26  10:07:42  kjb

* Took out extern references

* 

* Revision 1.4  91/09/01  17:18:24  ROOT_DOS

* Changed prototype for lst_deletenext().

* 

* Revision 1.3  91/09/01  15:15:46  ROOT_DOS

* Changed search for include files to include current directory

* 

* Added function lst_kill().

* 

* Revision 1.2  91/08/22  11:06:50  ROOT_DOS

* Header file for corresponding revision of source module

* 

* Revision 1.1  91/08/21  14:11:39  ROOT_DOS

* Initial revision

* 

****************************************************************************/



#ifndef	__LIST_H

#define	__LIST_H



#ifndef	__DEBUG_H

#include "debug.h"

#endif



/*---------------------- Macros and type definitions ----------------------*/



typedef struct LST_BUCKET {

	struct LST_BUCKET	*next;

	} LST_BUCKET;



typedef struct {

	int			count;			/* Number of elements currently in list	*/

	LST_BUCKET	*head;			/* Pointer to head element of list		*/

	LST_BUCKET	*z;				/* Pointer to last node of list			*/

	LST_BUCKET	hz[2];			/* Space for head and z nodes			*/

	} LIST;



/* Return a pointer to the user space given the address of the header of

 * a node.

 */



#define	LST_USERSPACE(h)	((void*)((LST_BUCKET*)(h) + 1))



/* Return a pointer to the header of a node, given the address of the

 * user space.

 */



#define	LST_HEADER(n)		((LST_BUCKET*)(n) - 1)



/* Return a pointer to the user space of the list's head node. This user

 * space does not actually exist, but it is useful to be able to address

 * it to enable insertion at the start of the list.

 */



#define	LST_HEAD(l)			LST_USERSPACE((l)->head)



/* Determine if a list is empty

 */



#define	LST_EMPTY(l)		((l)->count == 0)



/*-------------------------- Function Prototypes --------------------------*/



#ifdef __cplusplus

extern "C" {

#endif



void *lst_newnode(int size);

void lst_freenode(void *node);

LIST *lst_init(void);

void lst_kill(LIST *l,void (*freeNode)());

void lst_insertafter(LIST *l,void *node,void *after);

void *lst_deletenext(LIST *l,void *node);

void *lst_first(LIST *l);

void *lst_next(void *prev);

void lst_mergesort(LIST *l,int (*cmp_func)());



#ifdef __cplusplus

}

#endif



#endif

Code:
/****************************************************************************

*

*					Copyright (C) 1991 Kendall Bennett.

*							All rights reserved.

*

* Filename:		$RCSfile: list.c $

* Version:		$Revision: 1.9 $

*

* Language:		ANSI C

* Environment:	any

*

* Description:	Module to implement linked lists. Includes a routine to

*				peform a mergesort on the linked list.

*

* $Id: list.c 1.9 91/12/31 19:40:15 kjb Exp $

*

* Revision History:

* -----------------

*

* $Log:	list.c $

* Revision 1.9  91/12/31  19:40:15  kjb

* Modified include file directories.

* 

* Revision 1.8  91/10/28  03:17:14  kjb

* Ported to the Iris.

* 

* Revision 1.7  91/09/03  18:28:15  ROOT_DOS

* Ported to UNIX.

* 

* Revision 1.6  91/09/01  17:31:07  ROOT_DOS

* Fixed bug in lst_deletenext().

* 

* Revision 1.5  91/09/01  17:17:37  ROOT_DOS

* Changed lst_deletenext() to return a pointer to the deleted node's

* userspace.

* 

* Revision 1.4  91/09/01  16:04:09  ROOT_DOS

* Minor cosmetic change

* 

* Revision 1.3  91/09/01  01:49:59  ROOT_DOS

* Changed search for include files to search the current directory.

* 

* Added function lst_kill() to delete the nodes in the list, calling a user

* supplied function to kill each node.

* 

* Revision 1.2  91/08/21  14:32:02  ROOT_DOS

* Optimized the mergesort routine by eliminating passing the end of the

* merged list found in merge(), back to the main mergesort() routine. This

* eliminated the need to traverse the newly merged list to find the end. 

* Gives about 10% speed improvement for moderate size lists.

* 

* Revision 1.1  91/08/21  14:10:39  ROOT_DOS

* Initial revision

* 

****************************************************************************/



#include <stdio.h>

#include <malloc.h>

#include <signal.h>

#include "debug.h"

#include "list.h"



PUBLIC void *lst_newnode(int size)

/****************************************************************************

*

* Function:		lst_newnode

* Parameters:	size	- Amount of memory to allocate for node

* Returns:      Pointer to the allocated node's user space.

*

* Description:	Allocates the memory required for a node, adding a small

*				header at the start of the node. We return a reference to

*				the user space of the node, as if it had been allocated via

*				malloc().

*

****************************************************************************/

{

	LST_BUCKET	*node;



	if ( !(node = (LST_BUCKET*)malloc(size + sizeof(LST_BUCKET))) ) {

		fprintf(stderr,"Not enough memory to allocate list node.\n");

		raise(SIGABRT);

		return NULL;

		}



	return LST_USERSPACE(node);			/* Return pointer to user space */

}



PUBLIC void lst_freenode(void *node)

/****************************************************************************

*

* Function:		lst_freenode

* Parameters:	node	- Node to free.

*

* Description:  Frees a node previously allocated with lst_newnode().

*

****************************************************************************/

{

	free(LST_HEADER(node));

}



PUBLIC LIST *lst_init(void)

/****************************************************************************

*

* Function:		lst_init

* Returns:      Pointer to a newly created list.

*

* Description:	Initialises a list and returns a pointer to it.

*

****************************************************************************/

{

	LIST	*l;



	if ((l = (LIST*)malloc(sizeof(LIST))) != NULL) {

		l->count = 0;

		l->head = &(l->hz[0]);

		l->z = &(l->hz[1]);

		l->head->next = l->z->next = l->z;

		}

	else {

		fprintf(stderr,"Insufficient memory to allocate list\n");

		raise(SIGABRT);

		return NULL;

		}



	return l;

}



PUBLIC void lst_kill(LIST *l,void (*freeNode)(void *node))

/****************************************************************************

*

* Function:		lst_kill

* Parameters:	l			- List to kill

*				freeNode	- Pointer to user routine to free a node

*

* Description:	Kills the list l, by deleting all of the elements contained

*				within the list one by one and then deleting the list

*				itself. Note that we call the user supplied routine

*				(*freeNode)() to free each list node. This allows the user

*				program to perform any extra processing needed to kill each

*				node (if each node contains pointers to other items on the

*				heap for example). If no extra processing is required, just

*				pass the address of lst_freenode(), ie:

*

*					lst_kill(myList,lst_freenode);

*

****************************************************************************/

{

	LST_BUCKET	*n,*p;



	n = l->head->next;

	while (n != l->z) {			/* Free all nodes in list				*/

		p = n;

		n = n->next;

		(*freeNode)(LST_USERSPACE(p));

		}

	free(l);					/* Free the list itself					*/

}



PUBLIC void lst_insertafter(LIST *l,void *node,void *after)

/****************************************************************************

*

* Function:		lst_insertafter

* Parameters:	l		- List to insert node into

*				node	- Pointer to user space of node to insert

*				after	- Pointer to user space of node to insert node after

*

* Description:	Inserts a new node into the list after the node 'after'. To

*				insert a new node at the beginning of the list, user the

*				macro LST_HEAD in place of 'after'. ie:

*

*					lst_insertafter(mylist,node,LST_HEAD(mylist));

*

****************************************************************************/

{

	LST_BUCKET	*n = LST_HEADER(node),*a = LST_HEADER(after);



	n->next = a->next;

	a->next = n;

	l->count++;

}



PUBLIC void *lst_deletenext(LIST *l,void *node)

/****************************************************************************

*

* Function:		lst_deletenext

* Parameters:	l		- List to delete node from.

*				node	- Node to delete the next node from

* Returns:		Pointer to the deleted node's userspace.

*

* Description:	Removes the node AFTER 'node' from the list l.

*

****************************************************************************/

{

	LST_BUCKET	*n = LST_HEADER(node);



	node = LST_USERSPACE(n->next);

	n->next = n->next->next;

	l->count--;

	return node;

}



PUBLIC void *lst_first(LIST *l)

/****************************************************************************

*

* Function:		lst_first

* Parameters:	l		- List to obtain first node from

* Returns:		Pointer to first node in list, NULL if list is empty.

*

* Description:	Returns a pointer to the user space of the first node in

*				the list. If the list is empty, we return NULL.

*

****************************************************************************/

{

	LST_BUCKET	*n;



	n = l->head->next;

	return (n == l->z ? NULL : LST_USERSPACE(n));

}



PUBLIC void *lst_next(void *prev)

/****************************************************************************

*

* Function:		lst_next

* Parameters:	prev	- Previous node in list to obtain next node from

* Returns:		Pointer to the next node in the list, NULL at end of list.

*

* Description:	Returns a pointer to the user space of the next node in the

*				list given a pointer to the user space of the previous node.

*				If we have reached the end of the list, we return NULL. The

*				end of the list is detected when the next pointer of a node

*				points back to itself, as does the dummy last node's next

*				pointer. This enables us to detect the end of the list

*				without needed access to the list data structure itself.

*

*				NOTE:	We do no checking to ensure that 'prev' is NOT a

*						NULL pointer.

*

****************************************************************************/

{

	LST_BUCKET	*n = LST_HEADER(prev);



	n = n->next;

	return (n == n->next ? NULL : LST_USERSPACE(n));

}



/* Static globals required by merge()	*/



static LST_BUCKET	*z;

static int 			(*cmp)(void*,void*);



PRIVATE LST_BUCKET *merge(LST_BUCKET *a,LST_BUCKET *b,LST_BUCKET **end)

/****************************************************************************

*

* Function:		merge

* Parameters:	a,b		- Sublist's to merge

* Returns:		Pointer to the merged sublists.

*

* Description:	Merges two sorted lists of nodes together into a single

*				sorted list.

*

****************************************************************************/

{

	LST_BUCKET	*c;



	/* Go through the lists, merging them together in sorted order	*/



	c = z;

	while (a != z && b != z) {

		if ((*cmp)(LST_USERSPACE(a),LST_USERSPACE(b)) <= 0) {

			c->next = a; c = a; a = a->next;

			}

		else {

			c->next = b; c = b; b = b->next;

			}

		};



	/* If one of the lists is not exhausted, then re-attach it to the end

	 * of the newly merged list

	 */



	if (a != z) c->next = a;

	if (b != z) c->next = b;



	/* Set *end to point to the end of the newly merged list	*/



	while (c->next != z) c = c->next;

	*end = c;



	/* Determine the start of the merged lists, and reset z to point to

	 * itself

	 */



	c = z->next; z->next = z;

	return c;

}



PUBLIC void lst_mergesort(LIST *l,int (*cmp_func)(void*,void*))

/****************************************************************************

*

* Function:		lst_mergesort

* Parameters:	l			- List to merge sort

*				cmp_func	- Function to compare two user spaces

*

* Description:	Mergesort's all the nodes in the list. 'cmp' must point to

*				a comparison function that can compare the user spaces of

*				two different nodes. 'cmp' should work the same as

*				strcmp(), in terms of the values it returns.

*

****************************************************************************/

{

	int			i,N;

	LST_BUCKET	*a,*b;		/* Pointers to sublists to merge			*/

	LST_BUCKET	*c;			/* Pointer to end of sorted sublists		*/

	LST_BUCKET	*head;		/* Pointer to dummy head node for list		*/

	LST_BUCKET	*todo;		/* Pointer to sublists yet to be sorted		*/

	LST_BUCKET	*t;			/* Temporary								*/



	/* Set up globals required by merge() and pointer to head	*/



	z = l->z; cmp = cmp_func; head = l->head;



	for (N = 1,a = z; a != head->next; N = N + N) {

		todo = head->next; c = head;

		while (todo != z) {



			/* Build first sublist to be merged, and splice from main list

			 */



			a = t = todo;

			for (i = 1; i < N; i++) t = t->next;

			b = t->next; t->next = z; t = b;



			/* Build second sublist to be merged and splice from main list

			 */



			for (i = 1; i < N; i++) t = t->next;

			todo = t->next; t->next = z;



			/* Merge the two sublists created, and set 'c' to point to the

			 * end of the newly merged sublists.

			 */



			c->next = merge(a,b,&t); c = t;

			}

		}

}