我目前正在研究数据结构,所以在我检查实现数组列表之后,我想看看在C中实现链接列表是否有什么问题。
#ifndef _LINKEDLIST_H
#define _LINKEDLIST_H
#include <stddef.h> /* size_t */
#include <stdbool.h> /* _Bool */
#define _LINKEDLIST_DEFAULT_SIZE (1)
typedef struct _linkedlist _LinkedList;
typedef const unsigned int Index;
#define LinkedList _LinkedList *
LinkedList LinkedList_create();
int LinkedList_add(LinkedList, void *);
int LinkedList_get_val_index(LinkedList, void *);
int LinkedList_get_list_index(LinkedList, const LinkedList *);
int LinkedList_remove(LinkedList, const _Bool, const _Bool);
void LinkedList_set_data(LinkedList, void **, const _Bool, const size_t max);
void LinkedList_clear(LinkedList, const _Bool);
void LinkedList_destroy(LinkedList *, const _Bool);
void *LinkedList_get_value(const LinkedList);
LinkedList LinkedList_get(LinkedList, Index);
LinkedList *LinkedList_get_next(LinkedList);
LinkedList *LinkedList_get_previous(LinkedList);
LinkedList *LinkedList_get_pointer(LinkedList *, Index);
inline size_t LinkedList_get_size_of(const LinkedList);
inline size_t LinkedList_get_size(const LinkedList);
#endif /* _LINKEDLIST_H */
#include <stdlib.h>
#include "LinkedList.h"
#define VALID_LINKEDLIST_CODE (245)
#define _LinkedList_check(l) \
if ((l) == NULL || (l)->_Valid != VALID_LINKEDLIST_CODE) \
abort();
struct _linkedlist {
size_t depth;
int _Valid;
void * value;
struct _linkedlist *next;
struct _linkedlist *previous;
};
struct _linkedlist *LinkedList_create(void * initial_value)
{ /* Allocate Memory */
struct _linkedlist *list = malloc(sizeof(struct _linkedlist));
if(list == NULL)
return NULL;
list->depth = 1;
list->next = NULL;
list->previous = NULL;
list->value = initial_value;
list->_Valid = VALID_LINKEDLIST_CODE;
return list;
}
void LinkedList_set_data(struct _linkedlist * list, void ** data, const _Bool freeval, const size_t max)
{ /* Sets the internal array of the arraylist */
_LinkedList_check(list);
int length;
for(length = 0; data[length]; ++length);
if (length < max || max == 0)
abort();
LinkedList_clear(list, freeval);
list->value = data[0];
for(unsigned int i = 1; i < max; ++i)
LinkedList_add(list, data[i]);
list->depth = max;
}
int LinkedList_add(struct _linkedlist *list, void *elem)
{ /* Adds one linked list to the chain with elem as value */
_LinkedList_check(list);
++list->depth;
struct _linkedlist ** l;
for(l = &list->next; ( *l != NULL ); l = &(*l)->next)
++(*l)->depth;
(*l) = LinkedList_create(elem);
(*l)->previous = *l;
return ((*l)->next == NULL);
}
struct _linkedlist *LinkedList_get(struct _linkedlist *list, const unsigned int index)
{ /* Gets the index'th linked list in the chain */
_LinkedList_check(list);
if (index >= list->depth)
return NULL;
for(unsigned int i = 0; i < index; list = list->next, i++);
return list;
}
struct _linkedlist **LinkedList_get_pointer(struct _linkedlist ** list, const unsigned int index)
{ /* Gets the index'th linked list in the chain as a pointer */
_LinkedList_check(*list);
if (index >= (*list)->depth)
return NULL;
for(unsigned int i = 0; i < index; list = &(*list)->next);
return list;
}
inline size_t LinkedList_get_size_of(const struct _linkedlist *list)
{ /* Returns the size of the chain of lists in memory */
_LinkedList_check(list);
return (sizeof(struct _linkedlist) * list->depth);
}
inline size_t LinkedList_get_size(const struct _linkedlist *list)
{ /* Returns the number of elements in the arraylist */
_LinkedList_check(list);
return list->depth;
}
int LinkedList_remove(struct _linkedlist * list, const _Bool index, const _Bool freeval)
{ /* Removes one element at a chain index */
_LinkedList_check(list);
if (index >= list->depth)
return 2;
LinkedList_clear(LinkedList_get(list, index), freeval);
--list->depth;
return 0;
}
void LinkedList_clear(struct _linkedlist * list, const _Bool freeval)
{ /* Clears the list chain */
_LinkedList_check(list);
struct _linkedlist * l, * n;
for( l = list->next; l; l = n) {
if (freeval)
free(l->value);
n = l->next;
free(l);
}
list->next = NULL;
}
void LinkedList_destroy(struct _linkedlist ** list, const _Bool freeval)
{ /* De-allocates the list and its chains from memory
No usage of list is allowed after this function call */
_LinkedList_check(*list);
LinkedList_clear(*list, freeval);
free(*list);
*list = NULL;
}
int LinkedList_get_val_index(struct _linkedlist *list, void *elem)
{ /* Looks for elem in list and returns the index or -1 if not found */
_LinkedList_check(list);
for(unsigned int i = 0; i < list->depth; ++i)
if (elem == (LinkedList_get(list, i)->value))
return i;
return -1;
}
int LinkedList_get_list_index(struct _linkedlist *list, const struct _linkedlist ** elem)
{
_LinkedList_check(list);
for(unsigned int i = 0; i < list->depth; ++i)
if (*elem == LinkedList_get(list, i))
return i;
return -1;
}
void *LinkedList_get_value(const struct _linkedlist *list)
{ /* Return the list's essence, the value */
return list->value;
}
struct _linkedlist **LinkedList_get_next(struct _linkedlist *list)
{ /* Return the next list in the chain */
return &list->next;
}
struct _linkedlist **LinkedList_get_previous(struct _linkedlist *list)
{ /* Return the previous line in the chain */
return &list->previous;
}
在与val差制检查之后,我发现我没有内存泄漏,没有读/写错误,也没有函数或逻辑错误(测试后)。
我想知道代码中是否存在可用性或性能问题。
发布于 2014-10-05 11:21:38
您的列表有点不寻常,因为它在每个列表节点中都包含一个depth
字段和一个有效性检查字段。我从来没有见过这个,并认为深度,特别是一个错误。您的函数必须遍历整个列表,随时调整每个项的depth
字段。同样,当删除项目时,您必须遍历其余的项。这意味着列表在扩展时会变慢。这不是一个好的设计。
我认为最好从每个节点中删除depth
,并可能使列表头成为一个不同的结构,其中包含指向列表末尾的指针。
其他一些意见:
linkedlist_check
宏应该大写,并且应该使用do {...} while(0)
,而不是以分号结尾。LinkedList_set_data
中,第一个for -循环似乎在数据数组中搜索空指针。如果找不到,它将不确定地重复(进入未定义的内存)。我不知道为什么这个功能会有必要。LinkedList_add
不测试对LinkedList_create
的调用是否失败。函数还使用双指针编写,这是丑陋和不必要的。LinkedList_get
和LinkedList_get_pointer
都有意义。另外,后者不增加i
。LinkedList_get_size_of
没有用。调用方为什么要知道非连续(不透明)节点占用的内存量?返回节点数可能有更多的用途(LinkedList_get_size
)。LinkedList_remove
应该只删除一个节点,但在该节点之后“清除”列表。它似乎改变了列表头的深度计数器,而没有更改其他节点的深度计数器。..。我没有走得更远。
https://codereview.stackexchange.com/questions/64772
复制