如何在C中实现链表?

ant*_*009 8 c linked-list

我正在创建一个链接列表,就像我上一个问题一样.我发现开发链表的最好方法是将头部和尾部放在另一个结构中.我的产品结构将嵌套在这个结构中.我应该将列表传递给添加和删除功能.我发现这个概念令人困惑.

我已经实现了initialize,add和clean_up.但是,我不确定我是否正确地做到了这一点.

当我将产品添加到列表中时,我使用calloc声明了一些内存.但我想我不应该为产品声明内存.我对此添加感到困惑.

非常感谢任何建议,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PRODUCT_NAME_LEN 128

typedef struct product_data 
{
    int product_code;
    char product_name[PRODUCT_NAME_LEN];
    int product_cost;
    struct product_data_t *next;
}product_data_t;

typedef struct list 
{
    product_data_t *head;
    product_data_t *tail;
}list_t;

void add(list_t *list, int code, char name[], int cost); 
void initialize(list_t *list);
void clean_up(list_t *list);

int main(void)
{
    list_t *list = NULL;

    initialize(list);
    add(list, 10, "Dell Inspiron", 1500);
    clean_up(list);

    getchar();

    return 0;
}

void add(list_t *list, int code, char name[], int cost)
{
    // Allocate memory for the new product
    list = calloc(1, sizeof(list_t));
    if(!list)
    {
        fprintf(stderr, "Cannot allocated memory");
        exit(1);
    }

    if(list)
    {
        // First item to add to the list
        list->head->product_code = code;
        list->head->product_cost = cost;
        strncpy(list->head->product_name, name, sizeof(list->head->product_name));
        // Terminate the string
        list->head->product_name[127] = '/0';
    } 
}

// Initialize linked list
void initialize(list_t *list)
{
    // Set list node to null
    list = NULL;
    list = NULL;
}

// Release all resources
void clean_up(list_t *list)
{    
    list_t *temp = NULL;

    while(list)
    {
        temp = list->head;
        list->head = list->head->next;
        free(temp);    
    }
    list = NULL;
    list = NULL;
    temp = NULL;
}
Run Code Online (Sandbox Code Playgroud)

==============================编辑=================== =========

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PRODUCT_NAME_LEN 64

// typedef struct product_data product_data_t;
typedef struct product_data 
{
    int product_code;
    char product_name[PRODUCT_NAME_LEN];
    int product_cost;
}product_data_t;

typedef struct list
{
    struct list *head;
    struct list *tail;
    struct list *next;
    struct list *current_node;
    product_data_t *data;

}list_t;

void add(list_t *list, int code, char name[], int cost); 

int main(void)
{
    list_t *list = NULL;
    list = initialize(list);
    add(list, 1001, "Dell Inspiron 2.66", 1299);

    add(list, 1002, "Macbook Pro 2.66", 1499);

    clean_up(list);

    getchar();

    return 0;
}

void add(list_t *list, int code, char name[], int cost)
{
    /* Allocate memory for the new product */
    product_data_t *product = (product_data_t*) calloc(1, sizeof(*product));
    if(!product)
    {
        fprintf(stderr, "Cannot allocate memory.");
        exit(1);
    }

    /* This is the first item in the list */
    product->product_code = code;
    product->product_cost = cost;
    strncpy(product->product_name, name, sizeof(product->product_name));
    product->product_name[PRODUCT_NAME_LEN - 1] = '\0';

    if(!list->head)
    {
        /* Assign the address of the product. */
        list = (list_t*) product;   
        /* Set the head and tail to this product */
        list->head = (list_t*) product;
        list->tail = (list_t*) product;
    }
    else
    {
        /* Append to the tail of the list. */
        list->tail->next = (list_t*) product;
        list->tail = (list_t*) product;
    }

    /* Assign the address of the product to the data on the list. */
    list->data = (list_t*) product;
}
Run Code Online (Sandbox Code Playgroud)

Cra*_*ght 6

可以说,您希望列表数据结构在其存储的数据外部.

说你有:

struct Whatever
{
   int x_;
}

然后你的列表结构如下所示:

struct Whatever_Node
{
   Whatever_Node* next_
   Whatever* data_
}

Ryan Oberoi同样评论,但没有例子.


Bra*_*lor 5

如果您想更好地了解链表的基础知识,请查看以下文档:

http://cslibrary.stanford.edu/103/LinkedListBasics.pdf


jhu*_*ord 5

在您的情况下,头和尾可以简单地指向链表的开头和结尾。对于单链表,实际上只需要头。最基本的是,可以仅使用如下结构来创建链接列表:

typedef struct listnode
{
   //some data
   struct listnode *next;
}listnodeT;

listnodeT *list;
listnodeT *current_node;
list = (listnodeT*)malloc(sizeof(listnodeT));
current_node = list;
Run Code Online (Sandbox Code Playgroud)

只要 list 始终指向列表的开头并且最后一项的 next 设置为 NULL,就可以使用 current_node 来遍历列表。但有时为了使遍历列表更容易并存储有关列表的任何其他数据,会使用头标记和尾标记,并将其包装到它们自己的结构中,就像您所做的那样。那么你的添加和初始化函数将类似于(减去错误检测)

    // Initialize linked list
void initialize(list_t *list)
{
    list->head = NULL;
    list->tail = NULL;
}

void add(list_t *list, int code, char name[], int cost)
{
    // set up the new node
    product_data_t *node = (product_data_t*)malloc(sizeof(product_data_t));
    node->code = code;
    node->cost = cost;
    strncpy(node->product_name, name, sizeof(node->product_name));
    node->next = NULL;

    if(list->head == NULL){ // if this is the first node, gotta point head to it
        list->head = node;
        list->tail = node;  // for the first node, head and tail point to the same node
    }else{
        tail->next = node;  // append the node
        tail = node;        // point the tail at the end
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,由于它是一个单链表,因此尾部仅在将项目附加到列表时才真正有用。要插入一个项目,您必须从头部开始遍历列表。尾部真正派上用场的是双向链表,它允许您从任一端开始遍历列表。你可以像这样遍历这个列表

// return a pointer to element with product code
product_data_t*  seek(list_t *list, int code){
   product_data_t* iter = list->head;
   while(iter != NULL)
       if(iter->code == code)
           return iter;
       iter = iter->next;
   }
   return NULL; // element with code doesn't exist
}
Run Code Online (Sandbox Code Playgroud)

很多时候,头和尾是完全构造的节点,它们本身用作标记来表示列表的开始和结束。它们本身不存储数据(更确切地说,它们的数据代表哨兵令牌),它们只是正面和背面的占位符。这可以更轻松地编写一些处理链表的算法,但代价是必须有两个额外的元素。总的来说,链表是灵活的数据结构,有多种实现方法。

哦,是的,尼克是对的,使用链表是掌握指针和间接的好方法。它们也是练习递归的好方法!熟练使用链表后,接下来尝试构建一棵树并使用递归来遍历树。