[英]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;
}
}
注意pers
和info
是局部變量,而不是全局變量。 僅在定義它們的范圍內使用它們並對其進行定義。 很好:很容易看到, 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_pers
並temp_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.