簡體   English   中英

LinkedLists的LinkedList

[英]LinkedList of LinkedLists C

我正在嘗試創建一個將用LinkedLists填充的LinkedList。 主LinkedList將包含字符名稱和描述,以及其內部LinkedList中包含多少個節點。 內部的LinkedList將保存它們出現的章節編號以及該章節的簡要說明。 因此,例如,角色Joe(名字)是King(描述符),出現在第4 7和10章中。因此,他將具有3個內部節點,並在其中描述自己在這些章節中所做的工作。 我認為我不是立即添加到列表中,因為當我調用以遍歷列表並打印所有內容時,我只會得到添加的第一個人。

我制作的兩個結構。

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

創建指針。

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

用於添加新字符的功能。

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

}

我的測試打印方法

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

主要方法

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

處理LinkedLists的LinkedList使我感到困惑,也許我只是錯過了一些很小的東西,或者也許是真的很大的東西,但是任何幫助都會很大。 幾乎忘了,代碼會編譯並輸出此...

    Joe, the King 2
4   had a child.

因為它打印出Joe的計數為2,所以我認為它在起作用。

pers_head之外的所有全局變量都應為pers_head變量。 只有一個頭,即人員列表的頭。 所有其他信息都包含在此列表中:其他人在爭奪next指針; 通過該人的info 最重要的是,沒有全球信息頭。 信息頭屬於每個人。

當打印人員和事件列表時,應通過兩個循環進行:

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

注意persinfo是局部變量,而不是全局變量。 僅在定義它們的范圍內使用它們並對其進行定義。 很好:很容易看到, pers只會遍歷所有人,沒有別的。

添加人員時,將立即創建一個新的人員節點。 但是,如果此人已經在列表中,則可能不需要新節點。 僅在確實需要時才創建節點。

您的add函數完成了很多工作:它分配並填充節點和信息,並組織列表。 如果您編寫單獨的函數來創建節點並向個人插入信息,則核心列表代碼看起來會更干凈。

可能的實現(變量名稱稍有更改或縮短)可能是:

#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;
}

如您所見,您的代碼將打印出第一個節點和子節點:( ("Joe", "the King", "had a child.", 4) ,這意味着您的插入至少在開始時是有效的。 該行結束后,意味着temp_pers = temp_pers->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;
}

您創建了一個temp_perstemp_pers分配了一些內容,但作用域結束后,該節點未連接到head_pers 因此,每次構造新的結構並將其分配給temp_pers您都不會將其輸入到主鏈接列表( head_pers )中,因此,每次您檢查循環中的條件時(此條件: while(temp_pers != NULL) ),然后檢查您創建的最后一個節點,由於它未鏈接到某物,因此它在下一個節點上為NULL。

解決方法: head_pers->next = temp_pers; 在其他部分。 現在,這將確保第二個節點已連接到第一個。 從現在開始,您創建的每個節點都應連接到列表的末尾。 您可以通過保存最后一個節點(O(1)時間)或遍歷每個加法器上的列表(O(n)時間)來完成此操作

add ,在循環后, temp_pers指向NULL 您需要保持指向列表中最后一個人的指針:

struct Person *last_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