【问题标题】:C program - linked list inside linked listC程序 - 链表内的链表
【发布时间】:2016-03-20 13:37:41
【问题描述】:

假设我想创建一个书籍列表,这些书籍有一个或多个作者,以及书中的主要人物。为此创建结构的最佳方法是什么?以下是准确的还是不同的设置?

struct name
{
char prefix[5];
char first[50];
char middle[50];
char last[50];
char suffix[5];
struct name *next; /* linked list   */
struct name *previous; /* linked list   */
};


struct book
{
 struct name authors;  
 struct name main_characters;
char title[100];   
char publisher[100]; 

结构书 *next; struct book *previous;

};

【问题讨论】:

  • authorsmain_characters 是列表的负责人,不是吗?它们应该是指针。

标签: c struct linked-list


【解决方案1】:

我认为您的计划很好,使用 authorsmain_characters 的指针。当您对书籍、作者和主要人物使用侵入式链表时,您可能会发现分解链表结构和操作很有帮助。

如果你声明这样的结构:

struct node
{
    struct node *next;
    struct node *previous;
};
typedef struct node node;

您可以将它作为第一个元素嵌入到每个类型中:

struct name
{
    node linked_list;
    char name_prefix[10];
    char name_first[50];
    char name_middle[50];
    char name_last[50];
    char name_suffix[5];
};

struct book
{
    node linked_list;
    name *authors;  
    name *main_characters;

    /* variables for book */
    char title[100];   /* the title of the book */
    char publisher[100]; /* publisher */
    //etc.
};

这使您的类型convertible to the node type。然后,您可以根据 node 类型定义链表操作:

void 
node_add_node(node **head, node *object)
{
    if (*head == NULL) {
        *head = object;
    }
    else {
        node *current, *previous;
        for (current = *head; current != NULL; current = current->next) {
            previous = current;
        }
        previous->next = object;
    }
}

然后定义类型安全的操作以将书籍添加到书籍列表并将名称添加到书籍:

void 
books_add_book(struct book **books, struct book *book)
{
    node_add_node((node**)books, (node*)book);
}

void
book_add_author(struct book *book, struct name *author)
{
    node_add_node((node**)&book->authors, (node*)author);
}

void
book_add_main_character(struct book *book, struct name *character)
{
    node_add_node((node**)&book->main_characters, (node*)character);
}

然后,实现构造函数:

void node_init(node *node)
{
    node->previous = NULL;
    node->next = NULL;
}

struct book *
book_create(const char *title, const char *publisher)
{
    struct book *b = malloc(sizeof(book));
    if (b) {
        node_init(&b->linked_list);
        b->authors = NULL;
        b->main_characters = NULL;
        strcpy(b->title, title);
        strcpy(b->publisher, publisher);
    }
    return b;
}

struct name *
name_create(const char *prefix, const char *first, const char *middle, 
    const char *last, const char *suffix)
{
    name *n = malloc(sizeof(name));
    if (n) {
        node_init(&n->linked_list);
        strcpy(n->name_prefix, prefix);
        strcpy(n->name_first, first);
        strcpy(n->name_middle, middle);
        strcpy(n->name_last, last);
        strcpy(n->name_suffix, suffix);
    }
    return n;
}

然后您可以创建这样的书籍(注意:我将您的 name_prefix 的大小增加到 10):

 struct book *books = NULL;
 struct book *b = book_create("War and Peace", "Wordsworth");
 struct name *n = name_create("Count", "Lev", "Nikolayevich", "Tolstoy", "");
 book_add_author(b, n);
 n = name_create("Count", "Pyotr", "Kirillovich", "Bezukhov", "");
 book_add_main_character(b, n);
 n = name_create("Countess", "Natalya", "Ilyinichna", "Rostova", "");
 book_add_main_character(b, n);
 books_add_book(&books, b);

【讨论】:

  • Martin,假设我有各种分隔文件,其中包含书籍、作者和主要角色。您提供的答案是否适合从文件中读取信息并创建列表。是否需要某种“外键”来关联文件中的数据。例如:` struct name { node linked_list; char book_id_fk[20]; //
  • 该评论的格式不太好。对不起
  • 在 none_add_node 中也得到一个未初始化的指针错误:previous->next = object;
  • 我没有将authorsmain_characters 初始化为NULL。已修复。
  • 如果您有不同的书籍或同名作者,您将需要一个合成外键,这在大型数据库中很可能发生。
【解决方案2】:

为此创建结构的最佳方法是什么?

什么是最好的取决于问题的细节,在某种程度上是见仁见智的问题。

以下是准确的还是不同的设置?

您提出的两个备选方案看起来都很合理。

第一种选择,两个名字structs 本身是本书struct 的成员,由于需要较少的动态分配,在某些情况下可能更方便一些。另一方面,它使每个内部链表的第一个元素成为一种特殊情况,这可能会使您的代码整体上更加复杂。

第二种选择,在书struct 中包含指向两个名称structs 的指针,这让您更加一致,并且它更好地适应了一个或两个内部列表为空的可能性。考虑到所有因素,这就是我可能会选择的那个。

【讨论】:

    【解决方案3】:

    您需要的数据结构大部分时间取决于您拥有的数据类型和您想要对其执行的操作。

    链表适合以下需求:

    1. 频繁插入和删除数据
    2. 数据量可能无法容纳在一个地方/或无法在第一时间获得。

    它带有以下问题:

    1. 搜索和检索数据的速度很慢
    2. 在您的代码中添加更多复杂性和间接性。

    据我所知,动态字符串数组(char 数组)足以满足 authors 的需要,或者如果您关心的是粒度,则可以使用指向 struct name 的指针数组,因为一本书可能有多个作者。

    如果你想要静态数组,下面可以为你做:

    #define MAX_AUTHOR_LIMIT 10
    struct boook {
        ...
        struct name *authors[MAX_AUTHOR_LIMIT];
        int author_count;
        ...
    }
    

    或者如果你想更好,你也可以使用动态数组。

    链接列表也是一种替代方法,但是对于不需要频繁插入删除的少量数据项使用链接并不是一个好主意,但是再次按照我指出的那样,您知道应用程序需要做什么来决定权衡的基础。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多