C程序 - 链表中的链表

时间:2016-03-20 13:37:42

标签: c struct linked-list

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

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]; 

struct book * next;     struct book * previous;

};

3 个答案:

答案 0 :(得分:2)

我认为您的计划很好,使用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);

答案 1 :(得分:1)

  

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

什么最佳取决于问题的细节,在某种程度上是一个意见问题。

  

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

你提出的两种选择看起来都很合理。

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

第二种选择,书籍struct包含指向两个名称struct的指针,可以提供更多的一致性,并且更好地适应一个或两个内部列表为空的可能性。考虑到所有事情,这是我可能会选择的那个。

答案 2 :(得分:0)

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

链接列表适合以下需求:

  1. 经常插入和删除数据
  2. 数据量可能不适合在一个地方/或首先可用。
  3. 它带有以下问题:

    1. 慢慢搜索和检索数据
    2. 为代码添加更多复杂性和方向。
    3. 据我所知,动态数组字符串(char数组)就足够了authors,或者你可以使用指向struct name的指针数组,如果粒度是你关心的话题因为一本书可能有多位作者。

      如果您想要静态数组,可以为您完成:

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

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

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