An example of a simplified problem
The difficulty of a linked list is that you must copy the list processing function to handle different objects, even if the logic is exactly the same. For example, two structure-like lists:
struct Struct_Object_A
{
int a;
int b;
Struct_Object_A *next;
}OBJECT_A;
typedef struct Struct_Object_B
{
int a;
int b;
int c;
Struct_Object_B *next;
}OBJECT_B;
The two structures defined above have only a small difference. There is only one integer variable between object_b and Object_a. However, in the compiler's view, they are still very different. You must copy the functions used to add, delete, and search lists for each object stored in the linked list. To solve this problem, you can use a union or struct with all three variables, where integer c is not used in all cases. This can become very complex and will create a bad programming style.
C Code Solution: Virtual Link List
One of the better solutions to this problem is the virtual list. A virtual list is a linked list that contains only the linked list pointers. Objects are stored behind a linked list structure. This is done by allocating memory to the linked list node, then allocating memory to the object, and then assigning that memory to the linked list node pointer as follows:
A realization of virtual chain table structure
typedef struct liststruct
{
liststruct *next;
}LIST, *pLIST;
pLIST Head = NULL;
pLIST AddToList(pLIST Head, void * data, size_t datasize)
{
pLIST newlist = NULL;
void *p;
// 分配节点内存和数据内存
newlist = (pLIST) malloc(datasize + sizeof(LIST));
// 为这块数据缓冲区指定一个指针
p = (void *)(newlist + 1);
// 复制数据
memcpy(p, data, datasize);
// 将这个节点指定给链表的表头
if(Head)
newlist->next = Head;
else
newlist->next = NULL;
Head = newlist;
return Head;
}
The linked list node is now based on the base of the copy of the data value. This version handles scalar values well, but does not handle objects with elements that are allocated with malloc or new. To process these objects, the LIST structure needs to contain a generic function pointer that frees up memory (either by closing the file or by invoking the Shutdown method) before removing the node from the list and lifting it.
A linked list with a function that unlocks
typedef void (*listnodedestructor) (void *);
typedef struct LISTSTRUCT
{
Listnodedestructor Destruc Tfunc;
Liststruct *next;
}list, *plist;
Plist addtolist (plist head, void * data, size_t datasize, Listnodedestructor destructor)
{
Plist newlist = NULL;
void *p;
//allocating node memory and data memory
NewList = (plist) malloc (datasize + sizeof (LIST));
Specify a pointer for this data buffer
P = (void *) (newlist + 1);
Copy Data
memcpy (p, data, datasize);
Newlist->destructfunc = destructor;
//Assign this node to the header of the linked list
if (head)
Newlist->next = heads;
else
Newlist->next = NULL;
head = NewList;
return head;
}
Void DeleteList (plist head)
{
plist Next;
while (head)
{
Next = Head->next
Head->destructfunc ((void *) head);
Free (head);
Head = Next;
}
}
typedef struct LISTDATASTRUCT
{
LPSTR p;
} List_data, *PLIST_DATA;
void Listdatadestructor (void *p)
{
//Type conversion to node pointer
plist PL = (plist) p;
Type conversion of the data pointer
Plist_data PLD = (plist_data) (pl + 1);
Delete pld->p;
}
plist head = NULL;
void Testlist ()
{
Plist_data d = new List_data;
D->p = new CHAR[24];
strcpy (d->p, "Hello");
Head = Addtolist (head, (void *) d, sizeof (Plist_data), listdatadestructor);
//The object has been copied, now delete the original object
Delete D;
d = new List_data;
D->p = new char[24];
strcpy (D->p, "World");
Head = Addtolist (head, (void *) d, sizeof (Plist_data), listdatadestructor);
Delete D;
//Release list
DeleteList (head);
}