您好我正在尝试实现通用链接列表。我有一些工作使用下面的代码,但我看不到一个明显和巧妙的方法来删除对全局指针(curr和root)的依赖,从而允许定义多个链接列表。如果我使用的是c ++,我可能只是将整个事物包装在一个类中,但是因为它只能看到一个手动处理并将root和curr传递给需要它们的函数的解决方案。我确信有比这更好的方法所以你会怎么做呢。 感谢
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct Node{
int value;
struct Node *next;
};
struct Node * curr = NULL;
struct Node * root = NULL;
struct Node * createList(int val){
struct Node *n = malloc(sizeof(struct Node));
if(n==NULL){
printf("Node creation failed\n");
return NULL;
}
n->value = val;
n->next = NULL;
root=curr=n;
return n;
}
struct Node * extendList(int val, bool end){
if(curr == NULL){
return createList(val);
}
struct Node * newNode = malloc(sizeof(struct Node));
if(newNode==NULL){
printf("Node creation failed\n");
return NULL;
}
newNode->value = val;
newNode->next = NULL;
if(end){
curr->next = newNode;
curr = newNode;
}
else{
newNode->next = root;
root=newNode;
}
return curr;
}
void printList(void){
struct Node *ptr = root;
while(ptr!=NULL){
printf("%d\n",ptr->value);
ptr = ptr->next;
}
return;
}
struct Node * pos_in_list(unsigned int pos, struct Node **prev){
struct Node * ptr = root;
struct Node * tmp = NULL;
unsigned int i = 0;
while(ptr!=NULL){
if(i == pos){
break;
}
tmp = ptr;
ptr=ptr->next;
i++;
}
*prev = tmp;
return ptr;
}
void deletefromlist(int pos){
struct Node * del = NULL;
struct Node * prev = NULL;
del = pos_in_list(pos,&prev);
if(del == NULL)
{
printf("Out of range\n");
}
else
{
if(prev != NULL)
prev->next = del->next;
if(del == curr)
{
curr = prev;
}
else if(del == root)
{
root = del->next;
}
}
free(del);
del = NULL;
}
void deleteList(){
struct Node * del = root;
while(curr!=NULL){
curr = del->next;
free(del);
del=curr;
}
root = NULL;
curr = NULL;
}
int main(void)
{
int i;
for(i=0;i<10;i++){
extendList(i,true);
}
for(i=10;i>0;i--){
extendList(i,false);
}
printList();
deletefromlist(5);
printList();
deleteList();
return 0;
}
答案 0 :(得分:3)
创建Node * root和Node * curr的结构
struct LinkedList{
struct Node * curr;
struct Node * next;
};
答案 1 :(得分:2)
您可以创建另一个struct
来保留curr
和root
。此结构将像“链接列表对象”前端一样运行,而您的node
结构将作为后端。另外一个好处是,您可以存储有关链表的其他属性,例如列表中的元素数。
struct LinkedList {
int numElements;
struct Node * curr;
struct Node * root;
};
您可以修改您的函数以使用此结构,一旦完成,好处是最终用户可以创建许多链接列表,他们所要做的就是调用函数并传入指针到LinkedList
结构。
答案 2 :(得分:1)
通常这样做的方法是给每个函数一个链表指针的参数。像这样:
struct Node * extendList(struct Node * head, int val, bool end){
if(head == NULL){
return createList(val);
}
struct Node * newNode = malloc(sizeof(struct Node));
if(newNode==NULL){
printf("Node creation failed\n");
return NULL;
}
newNode->value = val;
newNode->next = NULL;
struct Node * tail = head;
while (tail->next) tail = tail->next;
tail->next = newNode;
tail = newNode;
return newNode; // return the new node
}
这消除了对全局指针的任何需要,并允许任意数量的列表。事实上,我强烈建议你避免在这种情况下使用全局变量。
我已为check out的链接列表实施提交了评论。您可能想要检查批评,可能适用于您自己的实施。
答案 3 :(得分:1)
我在C中实现了一个通用列表。
它旨在用作静态库。列表操作(在通用数据上)从列表服务公开。正如你所问,
此列表服务以下列方式完成这两项功能,
创建新的链接列表后,此服务将返回表示它的唯一标识符,而不是传统的链接列表头指针。这样客户端代码就不能直接破坏链表。此列表服务允许创建多个链接列表。每个都有唯一的ID。完成后,客户端可以释放列表,服务可以在创建新列表后重新使用该列表。在任何方法中都必须维护每个列表的全局头指针,但这里隐藏在列表服务中。
以下是我的实施:
答案 4 :(得分:0)
看看伯克利派生的通用实现,了解如何做到这一点。