简体   繁体   English

LinkedLists的LinkedList

[英]LinkedList of LinkedLists C

Im trying to create a LinkedList that will be populated with LinkedLists. 我正在尝试创建一个将用LinkedLists填充的LinkedList。 The main LinkedList will hold a characters name and description, as well as how many nodes are held in its inner LinkedList. 主LinkedList将包含字符名称和描述,以及其内部LinkedList中包含多少个节点。 The inner LinkedList will hold the chapter number they appear in and a brief description for that chapter. 内部的LinkedList将保存它们出现的章节编号以及该章节的简要说明。 So for instance, character Joe(name) is a King(descriptor) and appears in chapters 4 7 and 10. So he would have 3 inner nodes with a description of what he did in those chapters. 因此,例如,角色Joe(名字)是King(描述符),出现在第4 7和10章中。因此,他将具有3个内部节点,并在其中描述自己在这些章节中所做的工作。 I don't think Im adding to the lists right though, because when I call to iterate through the lists and print everything, I only get the first person I added. 我认为我不是立即添加到列表中,因为当我调用以遍历列表并打印所有内容时,我只会得到添加的第一个人。

The two structs I made. 我制作的两个结构。

struct Person{
    char * name;
    char * descriptor;
    int count;
    struct Person * next;
    struct Information * info_head;
};
struct Information{
    char * text;
    int chapter;
    struct Information * next;
};

Creating pointers. 创建指针。

struct Person * new_person, *temp_pers, *head_pers;
struct Information * new_info, *temp_info, *head_info;

function used for adding new characters. 用于添加新字符的功能。

void add(char * name, char * descriptor, char * info, int chapter){
new_person = (struct Person *)malloc(sizeof(struct Person));
new_info = (struct Information *)malloc(sizeof(struct Information));

new_info->chapter = chapter;
new_info->text = info;
new_person->name = name;
new_person->descriptor = descriptor;

if(head_pers == NULL){  //List is empty
    head_pers = new_person; //add new person
    new_person->info_head = new_info;//link to information
    head_pers->next = NULL;
    head_info = new_info; //name that information start of information list
    head_pers->count = 1;
    head_info->next = NULL;
}
else{
    temp_pers = head_pers;
    temp_info = head_info;
    while(temp_pers != NULL){ //iterate through list of people
        if(strcmp(temp_pers->name, name) == 0){ //adding a duplicate
            while(temp_info != NULL){ //iterate through that persons info list
                temp_info = temp_info->next;
            } //reached the end of the list
            temp_info = new_info;
            temp_pers->count = temp_pers->count + 1;
            temp_pers->next = NULL;
        }
        temp_pers = temp_pers->next;
    }
    //reached end of persons list with no find
    //add new person to the end of the list
    temp_pers = new_person;
    temp_pers->count = temp_pers->count + 1;
    temp_pers->next = NULL;
}

} }

My printing method for testing 我的测试打印方法

void printAll(){
    temp_pers = head_pers;
    temp_info = head_info;
    while(temp_pers != NULL){
        printf("%s, %s %d\n", temp_pers->name, temp_pers->descriptor, temp_pers->count);
        while(temp_info != NULL){
            printf("%d\t%s", temp_info->chapter, temp_info->text);
            temp_info = temp_info->next;
        }
        temp_pers = temp_pers->next;
    }
}

Main method 主要方法

int main(){
    add("Joe", "the King", "had a child.", 4);
    add("Joe", "the King", "started a war", 7);
    add("Sue", "the Queen", "poisoned Joe", 10);

    printAll();

    return 0;
}

Dealing with a LinkedList of LinkedLists is confusing me and maybe I'm just missing something really small, or maybe something really big, but any help would be great. 处理LinkedLists的LinkedList使我感到困惑,也许我只是错过了一些很小的东西,或者也许是真的很大的东西,但是任何帮助都会很大。 Almost forgot, the code does compile and outputs this... 几乎忘了,代码会编译并输出此...

    Joe, the King 2
4   had a child.

Because its printing out the count for Joe as 2, I think it's working some what. 因为它打印出Joe的计数为2,所以我认为它在起作用。

All your global variables except the pers_head should be locals. pers_head之外的所有全局变量都应为pers_head变量。 There is only one head, namely the head of the person list. 只有一个头,即人员列表的头。 All other information is contained within this list: Other persons vie the next pointers; 所有其他信息都包含在此列表中:其他人在争夺next指针; information via the person's info . 通过该人的info Most importantly, there is no global info head; 最重要的是,没有全球信息头。 the info head belongs to each person. 信息头属于每个人。

When you print your list of persons and events, you should do so with two loops: 当打印人员和事件列表时,应通过两个循环进行:

void printAll()
{
    struct Person *pers = head;

    while (pers) {
        printf("%s, %s [%d]\n",
            pers->name, pers->desc, pers->count);

        struct Information *info = pers->info;

        while (info) {
            printf("    %d: %s\n", info->chapter, info->text);
            info = info->next;
        }

        pers = pers->next;
    }
}

Note how pers and info are local variables, not global. 注意persinfo是局部变量,而不是全局变量。 They are used and have a meaining only in the scope where they are defined. 仅在定义它们的范围内使用它们并对其进行定义。 That's good: It is easy to see that pers just iterates over all persons, nothing else. 很好:很容易看到, pers只会遍历所有人,没有别的。

When you add a person, you create a new person node right away. 添加人员时,将立即创建一个新的人员节点。 But you might not need a new node if the person is already in the list. 但是,如果此人已经在列表中,则可能不需要新节点。 Create the node only if you really need it. 仅在确实需要时才创建节点。

Your add function does too much stuff: It allocates and populates the nodes and infos and it organises the lists. 您的add函数完成了很多工作:它分配并填充节点和信息,并组织列表。 If you write separate functions to create nodes and to insert an info to a person, the core list code will look cleaner. 如果您编写单独的函数来创建节点并向个人插入信息,则核心列表代码看起来会更干净。

A possible implementation (with slightly changed, or rather shortzened, variable names) could be: 可能的实现(变量名称稍有更改或缩短)可能是:

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

struct Person{
    char *name;
    char *desc;
    int count;
    struct Person *next;
    struct Information *info;
};
struct Information{
    char *text;
    int chapter;
    struct Information *next;
};

struct Person *head;

struct Information *info_new(char *text, int chapter)
{
    struct Information *info = malloc(sizeof(*info));

    info->text = text;
    info->chapter = chapter;
    info->next = NULL;

    return info;
}

struct Person *pers_new(char *name, char *desc)
{
    struct Person *pers = malloc(sizeof(*pers));

    pers->name = name;
    pers->desc = desc;
    pers->next = NULL;
    pers->info = NULL;
    pers->count = 0;

    return pers;
}

void pers_add_info(struct Person *pers, struct Information *info)
{
    if (pers->info == NULL) {
        pers->info = info;
    } else {
        struct Information *j = pers->info;

        while (j->next) j = j->next;
        j->next = info;
    }

    info->next = NULL;
    pers->count++;
}

void add(char *name, char *desc, char *infotext, int chapter)
{
    struct Information *info = info_new(infotext, chapter);
    struct Person *pers = head;
    struct Person *prev = NULL;

    while (pers) {
        if (strcmp(pers->name, name) == 0
         && strcmp(pers->desc, desc) == 0) {
            pers_add_info(pers, info);
            return;
        }
        prev = pers;
        pers = pers->next;
    }

    pers = pers_new(name, desc);
    pers_add_info(pers, info);

    if (prev) {
        prev->next = pers;
    } else {
        head = pers;
    }
}

void printAll()
{
    struct Person *pers = head;

    while (pers) {
        printf("%s, %s [%d]\n",
            pers->name, pers->desc, pers->count);

        struct Information *info = pers->info;

        while (info) {
            printf("    %d: %s\n", info->chapter, info->text);
            info = info->next;
        }

        pers = pers->next;
    }
}

int main()
{
    add("Joe", "the king", "had a child", 4);
    add("Sue", "the queen", "gave birth to a child", 4);
    add("Ben", "the prince", "is born", 4);
    add("Joe", "the king", "started a war", 7);
    add("Joe", "the king", "returns home victorious", 8);
    add("Ben", "the prince", "is squire to Lord Sam", 8);
    add("Sam", "High Lord", "takes Sam as apprentice", 8);
    add("Ben", "the prince", "goes on a quest", 9);
    add("Sue", "the queen", "poisoned Joe", 10);
    add("Ben", "the prince", "takes revenge", 10);
    add("Sam", "High Lord", "goes on a crusade", 11);
    add("Sue", "the queen", "repents", 14);
    add("Sue", "the hermit", "dies of old age and lonely", 14);

    printAll();

    return 0;
}

As you can see, your code prints out the first node and sub-node: ("Joe", "the King", "had a child.", 4) and that means your insertion is working, at least at start. 如您所见,您的代码将打印出第一个节点和子节点:( ("Joe", "the King", "had a child.", 4) ,这意味着您的插入至少在开始时是有效的。 After this line it terminates, meaning temp_pers = temp_pers->next == NULL; 该行结束后,意味着temp_pers = temp_pers->next == NULL;

Now, let's look at your second insertion: 现在,让我们看看您的第二次插入:

else{
temp_pers = head_pers;
temp_info = head_info;
while(temp_pers != NULL){ //iterate through list of people
    if(strcmp(temp_pers->name, name) == 0){ //adding a duplicate
        while(temp_info != NULL){ //iterate through that persons info list
            temp_info = temp_info->next;
        } //reached the end of the list
        temp_info = new_info;
        temp_pers->count = temp_pers->count + 1;
        temp_pers->next = NULL;
    }
    temp_pers = temp_pers->next;
}
//reached end of persons list with no find
//add new person to the end of the list
temp_pers = new_person;
temp_pers->count = temp_pers->count + 1;
temp_pers->next = NULL;
}

You created a temp_pers and assigned it something but after the scope ends, this node isn't connected to your head_pers . 您创建了一个temp_perstemp_pers分配了一些内容,但作用域结束后,该节点未连接到head_pers So, each time you construct a new struct and assign it to temp_pers you are not entering it to the main linked list ( aka head_pers ), so each time you check the condition inside your loop (this one: while(temp_pers != NULL) ) you check the last node you created, and since it isn't linked to something, it gives you NULL on the next node. 因此,每次构造新的结构并将其分配给temp_pers您都不会将其输入到主链接列表( head_pers )中,因此,每次您检查循环中的条件时(此条件: while(temp_pers != NULL) ),然后检查您创建的最后一个节点,由于它未链接到某物,因此它在下一个节点上为NULL。

How to fix: head_pers->next = temp_pers; 解决方法: head_pers->next = temp_pers; in the else section. 在其他部分。 Now, this will make sure the 2nd node is connected to the 1st. 现在,这将确保第二个节点已连接到第一个。 From now on, each node you create should be connected the the end of the list. 从现在开始,您创建的每个节点都应连接到列表的末尾。 You can do that by saving the last node (O(1) time), or by iterating through the list on each add (O(n) time) 您可以通过保存最后一个节点(O(1)时间)或遍历每个加法器上的列表(O(n)时间)来完成此操作

In add , after the loop, temp_pers points to NULL . add ,在循环后, temp_pers指向NULL You need to keep a pointer to the last person in the list: 您需要保持指向列表中最后一个人的指针:

struct Person *last_pers;

last_pers = temp_pers; last_pers = temp_pers;

while(temp_pers != NULL){ //iterate through list of people
    if(strcmp(temp_pers->name, name) == 0){ //adding a duplicate
        while(temp_info != NULL){ //iterate through that persons info list
            temp_info = temp_info->next;
        } //reached the end of the list
        temp_info = new_info;
        temp_pers->count = temp_pers->count + 1;
        temp_pers->next = NULL;
    }
    last_pers = temp_pers;
    temp_pers = temp_pers->next;
}
//reached end of persons list with no find
//add new person to the end of the list
last_pers->next = new_person;  
new_person->count = 1;
new_person->next = NULL;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM