可重用的链表实现

时间:2013-07-10 17:22:13

标签: c

您好我正在尝试实现通用链接列表。我有一些工作使用下面的代码,但我看不到一个明显和巧妙的方法来删除对全局指针(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;
}

5 个答案:

答案 0 :(得分:3)

创建Node * root和Node * curr的结构

struct LinkedList{
struct Node * curr;
struct Node * next;
};

答案 1 :(得分:2)

您可以创建另一个struct来保留currroot。此结构将像“链接列表对象”前端一样运行,而您的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中实现了一个通用列表。

它旨在用作静态库。列表操作(在通用数据上)从列表服务公开。正如你所问,

  1. 删除对全局指针(头部)的依赖性的简洁方法
  2. 定义多个链接列表。
  3. 此列表服务以下列方式完成这两项功能,

    创建新的链接列表后,此服务将返回表示它的唯一标识符,而不是传统的链接列表头指针。这样客户端代码就不能直接破坏链表。此列表服务允许创建多个链接列表。每个都有唯一的ID。完成后,客户端可以释放列表,服务可以在创建新列表后重新使用该列表。在任何方法中都必须维护每个列表的全局头指针,但这里隐藏在列表服务中。

    以下是我的实施:

    https://github.com/rajan-goswami/glist/wiki

答案 4 :(得分:0)

看看伯克利派生的通用实现,了解如何做到这一点。