One-way linked list implemented in C Language
List. C-a linked list by C
Cheungmine@gmail.com
(This article does not provide any protection. Therefore, you should fully consider the risks caused by using the code in this article. You cannot declare ownership of the Code in this article, but you do not need to inform me before using it for any purpose .)
This is my C-language one-way linked list. A one-way linked list is simple and can store any type of data: integer, string, or pointer type. However, do not mix. In addition to integers, the linked list node data is allocated and released by the caller. That is, the caller is responsible for providing a callback function. When the linked list is released, the caller automatically calls the function you provided. Remember: The linked list only allocates and manages its own private data without allocating any user data. Therefore, the user must allocate and release the data stored in the linked list. You can see the use case in the test code.
The files required for the linked list are: unistd. H, list. H, list. C. The test file is test. C. The following code is used:
/*************************************** **************************************** *********
* List. H *
* Generic sequential linked list node Structure -- can hold any type data .*
* Cheungmine *
* Mar. 22,200 8. All Rights Reserved .*
**************************************** **************************************** ********/
# Ifndef list_h_included __
# Define list_h_included __
# Ifdef _ cplusplus
Extern "C "{
# Endif
# Include "unistd. H"
Typedef struct _ listnode_t
{
Struct _ listnode_t * next;
Union {
Void * data;
Struct _ list_t * List;
Const char * STR;
Long key;
};
} Listnode_t;
Typedef struct _ list_t
{
Size_t size;/* count of nodes */
Listnode_t * head;
Listnode_t * tail;
} List_t, * list_p;
/**
* A prototype of callbacked function called:
*-List_destroy ()
*-List_traverse ()
*-List_node_free ()
* NULL for no use
*/
Typedef void (* pfunc_list_callback) (listnode_t * node );
/**
* An prototype example of free node data function implemented by Caller:
*/
Static void my_listnode_data_free (listnode_t * node)
{
Free (node-> data );
Dbg_trace ("my_listnode_data_free/N ");
}
/**
* A prototype example of traverse implemented by Caller:
*/
Static void my_listnode_key_traverse (listnode_t * node)
{
Printf ("Key = % LD/N", node-> key );
}
/**
* Traverses a list, applied callback functionn for each node
*/
Void
List_traverse (list_t * in_list, pfunc_list_callback pfcb_traversenode );
/**
* Allocates a empty list from heap, this creates a new list
*/
List_t *
List_create ();
/**
* Clears a list and free memory, the list cannot be used later
*/
Void
List_destroy (list_t * in_list, pfunc_list_callback pfcb_freedata );
/**
* Creates a new node assigned with data, not allocates for Data
*/
Listnode_t *
List_node_create (void * data );
/**
* Free a list node and IT & apos; s associated nodes, the freed node cannot be used later
*/
Void
List_node_free (listnode_t * node, pfunc_list_callback pfcb_freedata );
/**
* Creates a new node assigned with a key, not allocates for key
*/
Listnode_t *
List_key_create (long key );
/**
* Finds Prev node of given Node
*/
Listnode_t *
List_find_prev (const list_t * in_list, const listnode_t * node );
/**
* Appends a node to a list at back
*/
Void
List_push_back (list_t * in_list, listnode_t * node );
/**
* Inserts a node in front of head into a list
*/
Void
List_push_front (list_t * in_list, listnode_t * in_node );
/**
* Inserts a node after POS node into a list
*/
Void
List_insert_after (list_t * in_list, listnode_t * pos_node, listnode_t * in_node );
/**
* Inserts a node before POS node into a list
*/
Void
List_insert_before (list_t * in_list, listnode_t * pos_node, listnode_t * in_node );
/**
* Removes the first node from a list and returns it
*/
Listnode_t *
List_pop_front (list_t * in_list );
/**
* Removes the last node from a list and returns it
*/
Listnode_t *
List_pop_back (list_t * in_list );
/**
* Removes all nodes but for list itself
*/
Void
List_clear (list_t * in_list, pfunc_list_callback pfcb );
/**
* Returns a copy of a list_t from heap
*/
List_t *
List_copy (list_t list );
/**
* Concatenates two lists into first list
*/
Void
List_concat (list_t * First, list_t * second );
/**
* Gets count of nodes in the list
*/
Size_t
List_size (const list_t * in_list );
/**
* Gets node by index: 0-based. 0 is head
*/
Listnode_t *
List_node_at (const list_t * in_list, size_t index );
/**
* Slices list off from begin to end, returns begin Node
* Caller shoshould free returned list nodes
* Begin and end can be same one
*/
Listnode_t *
List_slice (list_t * in_list, listnode_t * begin, listnode_t * End );
# Ifdef _ cplusplus
}
# Endif
# Endif/* list_h_included __*/
/*************************************** **************************************** *********
* List. C *
* Generic sequential linked list node Structure -- can hold any type data .*
* Cheungmine *
* Mar. 22,200 8. All Rights Reserved .*
**************************************** **************************************** ********/
# Include "list. H"
Void
List_traverse (list_t * in_list, pfunc_list_callback pfcb)
{
Listnode_t * node;
Dbg_trace ("list_traverse:/n size = % LD/N", in_list-> size );
If (pfcb ){
Node = in_list-> head;
While (node ){
(* Pfcb) (node );
Node = node-> next;
}
}
}
List_t *
List_create ()
{
List_t * List = (list_t *) malloc (sizeof (list_t ));
List-> size = 0;
List-> head = List-> tail = NULL;
Dbg_trace ("list_create/N ");
Return list;
}
Void
List_destroy (list_t * in_list, pfunc_list_callback PF)
{
Dbg_trace ("list_destroy/N ");
List_clear (in_list, Pf );
Free (in_list );
}
Listnode_t *
List_node_create (void * Data)
{
Listnode_t * node = (listnode_t *) malloc (sizeof (listnode_t ));
Node-> next = NULL;
Node-> DATA = data;
Dbg_trace ("list_node_create/N ");
Return node;
}
Void
List_node_free (listnode_t * node, pfunc_list_callback pfcb)
{
Listnode_t * next;
Dbg_trace ("list_node_free/N ");
While (node ){
Next = node-> next;
If (pfcb)
(* Pfcb) (node );
Free (node );
Node = next;
}
}
Listnode_t *
List_key_create (long key)
{
Listnode_t * node = (listnode_t *) malloc (sizeof (listnode_t ));
Node-> next = NULL;
Node-> key = key;
Dbg_trace ("list_key_create: Key = % LD/N", key );
Return node;
}
Listnode_t *
List_find_prev (const list_t * in_list, const listnode_t * node)
{
Listnode_t * Prev;
Assert (node );
Prev = in_list-> head;
If (prev = node)
Return NULL;
While (prev & Prev-> next! = Node ){
Prev = Prev-> next;
}
Assert (prev );
Return Prev;
}
Void
List_push_back (list_t * in_list, listnode_t * node)
{
Node-> next = NULL;
If (in_list-> head)
{
In_list-> tail-> next = node;
In_list-> tail = node;
}
Else
In_list-> head = in_list-> tail = node;
In_list-> size ++;
Dbg_trace ("list_push_back/N ");
}
Void
List_push_front (list_t * in_list, listnode_t * in_node)
{
In_node-> next = in_list-> head;
In_list-> head = in_node;
If (! In_node-> next)
In_list-> tail = in_node;
In_list-> size ++;
Dbg_trace ("list_push_front/N ");
}
Void
List_insert_after (list_t * in_list, listnode_t * pos_node, listnode_t * in_node)
{
In_node-> next = pos_node-> next;
Pos_node-> next = in_node;
If (in_list-> tail = pos_node)
In_list-> tail = in_node;
In_list-> size ++;
}
Void
List_insert_before (list_t * in_list, listnode_t * pos_node, listnode_t * in_node)
{
Listnode_t * prev_node;
Prev_node = list_find_prev (in_list, pos_node );
If (prev_node)
List_insert_after (in_list, prev_node, in_node );
Else
List_push_front (in_list, in_node );
}
Listnode_t *
List_pop_front (list_t * in_list)
{
Listnode_t * pop_node = NULL;
If (in_list-> head)
{
Pop_node = in_list-> head;
In_list-> head = in_list-> head-> next;
If (in_list-> head = NULL)
In_list-> tail = NULL;
Pop_node-> next = NULL;
In_list-> size --;
}
Assert (in_list-> size> = 0 );
Dbg_trace ("list_pop_front/N ");
Return pop_node;
}
Listnode_t *
List_pop_back (list_t * in_list)
{
Listnode_t * pop_node = in_list-> tail;
If (in_list-> head = pop_node ){
In_list-> size = 0;
In_list-> head = in_list-> tail = NULL;
}
Else {
Assert (pop_node &&! Pop_node-> next );
In_list-> tail = list_find_prev (in_list, pop_node );
Assert (in_list-> tail );
In_list-> tail-> next = NULL;
In_list-> size --;
}
Assert (in_list-> size> = 0 );
Dbg_trace ("list_pop_back/N ");
Return pop_node;
}
Void
List_clear (list_t * in_list, pfunc_list_callback pfcb)
{
Listnode_t * node;
If (pfcb ){
While (node = list_pop_front (in_list ))){
(* Pfcb) (node );
Free (node );
}
}
Else {
While (node = list_pop_front (in_list ))){
Free (node );
}
}
Assert (in_list-> size = 0 );
Dbg_trace ("list_clear/N ");
}
List_t *
List_copy (list_t List)
{
List_t * newlist = (list_t *) malloc (sizeof (list_t ));
* Newlist = List;
Dbg_trace ("list_copy/N ");
Return newlist;
}
Void
List_concat (list_t * First, list_t * Second)
{
If (first-> head)
{
If (second-> head)
{
First-> tail-> next = Second-> head;
First-> tail = Second-> tail;
}
}
Else
* First = * second;
Second-> head = Second-> tail = NULL;
First-> size + = Second-> size;
Dbg_trace ("list_concat/N ");
}
Size_t
List_size (const list_t * in_list)
{
Dbg_trace ("list_size: % LD/N", in_list-> size );
Return in_list-> size;
}
Listnode_t *
List_node_at (const list_t * in_list, size_t index)
{
Size_t I = 0;
Listnode_t * node = in_list-> head;
Assert (index> = 0 & index <in_list-> size );
While (I <index ){
Node = node-> next;
I ++;
}
Return node;
}
Listnode_t *
List_slice (list_t * in_list, listnode_t * begin, listnode_t * end)
{
Listnode_t * Prev;
Assert (end );
Prev = list_find_prev (in_list, begin );
If (prev = NULL ){
Assert (begin = in_list-> head );
In_list-> head = end-> next;
End-> next = NULL;
If (in_list-> tail = end)
In_list-> tail = in_list-> head;
}
Else {
Prev-> next = end-> next;
End-> next = NULL;
If (in_list-> tail = end)
In_list-> tail = Prev;
}
Dbg_trace ("list_slice/N ");
In_list-> size = 0;
Prev = in_list-> head;
While (prev ){
In_list-> size ++;
Prev = Prev-> next;
}
Return begin;
}
/*************************************** **************************************** *********
* Unistd. H *
* 2008-03-15 last created by cheungmine .*
* All rights reserved by cheungmine .*
**************************************** **************************************** ********/
# Ifndef unistd_h __
# Define unistd_h __
/* Standard C header files encoded */
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <assert. h>
/* ===================================================== ================================================= */
# Ifndef have_int8
# Define have_int8
Typedef signed Char int8;/* NB: Non-ANSI compilers may not grok */
Typedef unsigned char uint8, uchar, byte, byte;
# Endif
# Ifndef have_int16
# Define have_int16
Typedef short int16;
Typedef unsigned short uint16, word_t, ushort;/* sizeof (uint16) Must = 2 */
# Endif
# Ifndef have_int32
# Define have_int32
Typedef int int32;
Typedef unsigned int uint32, size_t, dword_t;/* sizeof (uint32) Must = 4 */
Typedef unsigned long ulong;
# Endif
Typedef long lresult;
Typedef _ int64 int64, Longlong;
Typedef unsigned _ int64 uint64, qword_t, ulonglong;
# Ifndef bool
Typedef int bool;
# Define true 1
# Define false 0
# Endif
# Ifndef result
# Define result lresult
# DEFINE _ success 0
# DEFINE _ error-1
# Endif
# Ifndef in
# Define in
# Endif
# Ifndef out
# Define out
# Endif
# Ifndef inout
# Define inout
# Endif
# Ifndef optional
# Define optional
# Endif
# Define size_byte 1
# Define size_achar 1
# Define size_wchar 2
# Define size_short 2
# Define size_int 4
# Define size_long 4
# Define size_flt 4
# Define size_dbl 8
# Define size_word 2
# Define size_dword 4
# Define size_qword 8
# Define size_lint 8
# Define size_int64 8
# Define size_uuid 16
# Ifdef _ debug
# Include <stdarg. h>
Static void dbg_trace (const char * FMT ,...){
Va_list AP;
Va_start (AP, FMT );
Vprintf (FMT, AP );
Va_end (AP );
}
# Else
Static void dbg_trace (const char * FMT ,...){}
# Endif
/* ===================================================== ================================================= */
# Endif/* unistd_h __*/
Finally, the test project is:
//
// Test. C-test Topology
// Cheungmine@gmail.com
// 2008-3
//
# Include <stdio. h>
# Include <stdlib. h>
# Include "list. H"
Void list_use_key ()
{
Long K;
List_t * lst;
Listnode_t * nod;
LST = list_create ();
Assert (LST );
For (k = 1; k <= 10; k ++ ){
List_push_back (LST, list_key_create (k ));
}
List_size (LST );
List_pop_front (LST );
List_size (LST );
List_pop_back (LST );
List_size (LST );
List_traverse (LST, my_listnode_key_traverse );
Nod = list_slice (LST, LST-> head-> next, list_find_prev (LST, LST-> tail ));
List_node_free (nod, 0 );
List_traverse (LST, my_listnode_key_traverse );
List_destroy (LST, 0 );
}
Typedef struct
{
Char * _ Buff;
Size_t _ size;
} Blob;
Blob * blob_create (size_t N)
{
Blob * P = (BLOB *) malloc (sizeof (BLOB ));
P-> _ buff = (char *) malloc (N );
P-> _ size = N;
Dbg_trace ("blob_create/N ");
Return P;
}
Void blob_free (BLOB * P)
{
Free (p-> _ buff );
P-> _ size = 0;
Dbg_trace ("blob_free/N ");
}
Void my_listnode_blob_free (listnode_t * node)
{
Blob_free (BLOB *) node-> data );
}
Void my_listnode_blob_traverse (listnode_t * node)
{
Printf ("_ SIZE: % d, _ Buff: % s/n", (BLOB *) node-> data)-> _ size, (BLOB *) node-> data)-> _ buff );
}
Void list_use_data ()
{
Long K;
List_t * lst;
Blob * pb;
Listnode_t * nod;
LST = list_create ();
Assert (LST );
For (k = 1; k <= 10; k ++ ){
PB = blob_create (50 );
Sprintf_s (Pb-> _ buff, 50, "This is a blob: % d", k );
List_push_back (LST, list_node_create (PB ));
}
List_size (LST );
Nod = list_pop_front (LST );
Dbg_trace ("use blob here.../N ");
List_node_free (nod, my_listnode_blob_free );
List_size (LST );
Nod = list_pop_back (LST );
List_size (LST );
Dbg_trace ("use blob here.../N ");
List_node_free (nod, my_listnode_blob_free );
List_traverse (LST, my_listnode_blob_traverse );
Nod = list_slice (LST, LST-> head-> next, list_find_prev (LST, LST-> tail ));
List_node_free (nod, my_listnode_blob_free );
List_traverse (LST, my_listnode_blob_traverse );
List_destroy (LST, my_listnode_blob_free );
}
Int main ()
{
Printf ("========================== list_use_key ========================= /n ");
List_use_key ();
Printf ("============================ list_use_data ======================= /n ");
List_use_data ();
Printf ("-----------------/npress <enter> for quit! Cheungmine@gmail.com/N ");
Getchar ();
Return 0;
}