概括不同节点类型的链表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了概括不同节点类型的链表相关的知识,希望对你有一定的参考价值。
我有两种或更多种不同类型的结构使用它们自己的节点类型的链表,我注意到代码检索,删除,插入和检查节点是否存在的所有结构都是相同的,而代码是越来越重复。有没有更好的办法?
猫屋
typedef struct Cat Cat;
struct Cat {};
typedef struct CatNode CatNode;
struct CatNode {
char *name;
Cat *cat;
CatNode *next;
};
typedef struct CatHouse CatHouse;
struct CatHouse {
CatNode *cats;
Proxy *(*getCat)(const CatHouse *self, const char *name);
bool (*hasCat)(const CatHouse *self, const char *name);
Proxy *(*remove)(CatHouse *self, const char *name);
};
狗屋
typedef struct Dog Dog;
struct Dog {};
typedef struct DogNode DogNode;
struct DogNode {
char *name;
Dog *dog;
DogNode *next;
};
typedef struct DogHouse DogHouse;
struct DogHouse {
DogNode *dogs;
Dog *(*getDog)(const DogHouse *self, const char *name);
bool (*hasDog)(const DogHouse *self, const char *name);
Dog *(*remove)(DogHouse *self, const char *name);
};
这是在两个实体之间实现重复的实现的一部分。
我很好,如果复制是如何完成的,我也想知道链接列表是如何在商业项目中处理的,他们有几个实体结构,每个都有自己的链表,也许不止一个?
static bool hasCat(const Cat *self, const char *name) {
CatNode *cursor = self->cats;
while (cursor != NULL && strcmp(cursor->name, name) != 0)
cursor = cursor->next;
return cursor != NULL;
}
static bool hasDog(const Dog *self, const char *name) {
DogNode *cursor = self->dogs;
while (cursor != NULL && strcmp(cursor->name, name) != 0)
cursor = cursor->next;
return cursor != NULL;
}
除了类型不同之外,其他功能也同样重复。
答案
您可以使用C genericity以获得可以保存任何内容的链接列表。
一种方法是这样的:
typedef struct link {
void *data;
struct link *previous;
struct link *next;
} link_s;
typedef struct list {
link_s *head;
link_s *tail;
size_t nbLink;
/* function pointer */
int (*Data_Compare)(const void *data1, const void *data2);
void (*Data_Destructor)(void *data);
} list_s;
然后,你必须提供一个函数,用于知道哪个“数据”低于,等于或高于另一个(Data_Compare函数指针,就像strcmp一样),你可以提供一个“破坏”你的数据的函数(如果通过例如,你做了内存分配)。
在那之后,你可以让“数据”成为你的“猫”和“狗”结构的联合,从而允许一个链表保持全部,或者你可以有两个链表,一个用于“猫”,和其他一个“狗”(介意为两者提供良好的Data_Compare)。
在我的实现中,我提供了以下函数来操作list_s:
void List_Constructor(list_s *self, int (*Data_Compare)(const void *data1, const void *data2), void (*Data_Destructor)(void *data));
void List_Destructor(list_s *self);
bool List_Add(list_s *self, void *data);
void *List_RemoveByLink(list_s *self, link_s *link);
void *List_RemoveByData(list_s *self, void *data);
void *List_RemoveByCondition(list_s *self, bool (*Data_Condition)(const void *data));
void List_DestroyByLink(list_s *self, link_s *link);
/* Delete all the link corresponding to data */
void List_DestroyByData(list_s *self, void *data);
/* Delete all the link which condition is true */
void List_DestroyByCondition(list_s *self, bool (*Data_Condition)(const void *data));
void List_Sort(list_s *self);
void List_Merge(list_s *to, list_s *from);
void List_Reverse(list_s *self);
编辑:
为了通过以下示例获得线程安全功能,您可以进行如下操作:
typedef struct ts_list {
list_s list;
pthread_mutex_t mutex;
} ts_list_s;
void TsList_Constructor(ts_list_s *self, int (*Data_Compare)(const void *data1, const void *data2), void (*Data_Destructor)(void *data));
void TsList_Destructor(ts_list_s *self);
bool TsList_Add(ts_list_s *self, void *data);
void *TsList_RemoveByLink(ts_list_s *self, link_s *link);
void *TsList_RemoveByData(ts_list_s *self, void *data);
void *TsList_RemoveByCondition(ts_list_s *self, bool (*Data_Condition)(const void *data));
void TsList_DestroyByLink(ts_list_s *self, link_s *link);
void TsList_DestroyByData(ts_list_s *self, void *data);
void TsList_DestroyByCondition(ts_list_s *self, bool (*Data_Condition)(const void *data));
void TsList_Sort(ts_list_s *self);
void TsList_Merge(ts_list_s *to, ts_list_s *from);
void TsList_Reverse(ts_list_s *self);
// Addtionnal function, for comfort
bool TsList_LockMutex(ts_list_s *self);
bool TsList_UnlockMutex(ts_list_s *self);
所有TsList_ *函数看起来像:
bool TsList_Add(ts_list_s *self, void *data)
{
bool returnFunction;
if (!TsList_LockMutex(self)) {
return (false);
}
returnFunction = List_Add(&self->list, data);
if (!TsList_UnlockMutex(self)) {
// Big critical log, because from this point, there will be deadlock
}
return (returnFunction);
}
当然,你必须非常谨慎,尤其是使用“List_Merge”函数,因为你必须在合并之前锁定两个列表。
以上是关于概括不同节点类型的链表的主要内容,如果未能解决你的问题,请参考以下文章