创建一个链表,每个节点指向另一个链表

creating a linked list with each node pointing to another linked list

本文关键字:链表 节点 另一个 一个 创建      更新时间:2023-10-16

嘿,伙计们,我的代码应该创建一个学生链接列表,对于每个学生,它必须为该学生创建一个成绩链接列表。我真的不知道我的两个链表是否设置正确,因为当我试图遍历列表时,不会打印成绩。

struct Grade{
float score;
};
struct GradeNode{
Grade grade;
GradeNode *next_gnode;
};
struct StudentNode {
string name;
GradeNode *ghead;
StudentNode *next_snode;
};
StudentNode* head; //head of student linked list

下面的函数从一个文件中获取输入,并创建一个具有其值的节点,以及一个指向成绩链接列表的指针(ghead),最初设置为null。

void buildStudentList(string n){
StudentNode *newNode{ new StudentNode}; //initialize new Student node
StudentNode *curr; //to traverse thru Student lIst
//initialize student node
newNode->name = n;
newNode->next_snode = nullptr;
//have HEAD of THIS student's grades set to null, since there are no grades present for this student at this moment
newNode->ghead = nullptr;
//if student list is empty
if(!head){
//make this student node the head of the list
head = newNode;
}
else{
//else add it to the end of the list
curr = head;
//traverse to the end of the list
while(curr->next_snode){
curr= curr->next_snode;
}
//make grades for this student
buildGradeList(newNode->ghead, newNode->name);
//assign new node to the end of the list
curr->next_snode = newNode;
}
};

构建等级列表功能

//parameter is Grade Head, where we will attach a grade link list to it
void buildGradeList(GradeNode *head, string n){
//NOTE: head is HEAD OF GRADE LIST
bool quit = false;
int x;
while (!quit) {
cout<<"ENTER GRADE FOR "<<n<< ": (0 to quit)"<<endl;
cin>>x;
cout<<endl;
if(x==0){
//exit while loop and return      //when one presses 0, they go to the next student on the list!!!
quit=true;
}
else{
//append this value to head
appendGrades(head, x);
}
}
//return to prev function
return;
}

将成绩附加到链接列表中,头部仍然是ghead(该学生的成绩列表的头部)

void appendGrades(GradeNode *head, int s){
//create a new node with new score value
GradeNode *new_grade = {new GradeNode};
new_grade->grade.score = s;
new_grade->next_gnode = nullptr;
//node to traverse list
GradeNode *curr;
if(!head){
head = new_grade;
}else{
curr=head;
while (curr->next_gnode) {
curr= curr->next_gnode;
}
curr->next_gnode = new_grade;
}
};

如果有任何意见,我将不胜感激,伙计们!

实现最简单的解决方案是将buildGradeListappendGrades函数的签名中的GradeNode * head更改为GradeNode *& head。这会起作用,但我不建议你使用它,因为它没有抓住你锻炼的重点。

对我来说,你的代码似乎基本上是正确的(我还没有运行它,所以我不能确定,)除了一个问题:当你把成绩列表的头传递给这两个函数时,你会按值传递它。这意味着一个头部的副本,你所有的更改都将被复制到一个副本,这意味着它们不会生效,你的学生的GradeNode * ghead永远不会真正指向任何东西。

根据你在这里拥有的最正确的代码(根据我的经验,大多数程序员都在处理指针和链表),我认为你理解按值传递与传递指针/引用的概念。然而,为了能够使用指针,您必须明白指针本身只不过是一个地址,即一个值。因此,当您将指针传递到函数中时,您可以修改它所指向的对象的值,调用方将看到该更改,但您对指针本身所做的任何更改都将在函数结束时丢失,因为这些更改是对地址的副本所做的,这意味着您无法访问-因此无法更改-原始地址。

这一切都意味着,当向函数传递指针时,不能更改它指向的位置。但解决方案很简单。

当您想更改函数内int变量的值并让调用者看到更改时,您可以将该整数的地址以int *的形式传递给函数。因此,如果您想更改函数内"int*"变量的值(不是它指向的值,而是指针本身的值),则可以将该指针的地址以int **的形式传递给函数。

在你的情况下,这意味着你必须将我提到的两个函数的签名更改为:

void buildGradeList(GradeNode **head, string n);
void appendGrades(GradeNode **head, int s);

当然,你也必须对appendGrade的机身进行轻微的修改:

...
if(!*head){
*head = new_grade;
}else{
curr=*head;
...

这将是正确的,这将起作用,这将符合原始问题和您的解决方案的精神。

我在顶部建议的解决方案也有效,除了在函数签名中添加&(称为"引用",或者更准确地说是"左值引用")之外没有任何变化,因为这正是C++中的"引用"。引用是一个不需要特殊语法的指针(没有*来取消引用,也没有&来获取某个东西的地址

但我想提出一些更好的建议。两个占据成绩列表头部的函数也可能更改该列表。因此,我建议,与其接受指向列表头部的指针(或指向头部的指针的引用),他们可以始终将指针返回到头部。这意味着他们有时会返回一个新的头指针,有时会返回传递给他们的同一个指针,但他们自己不会更改实际的头指针;他们将他们认为应该是头的指针返回,并让打电话给他们的人来决定。

您需要进行的更改如下:

// First, change how we call buildGradeList inside buildStudentList:
newNode->ghead = buildGradeList(newNode->ghead, newNode->name);
// then, change the signature for buildGradeList:
GradeNode * buildGradeList (GradeNode * head, string n) {
// then, when you are calling appendGrades, store the value it returns in "head":
head = appendGrades(head, x);
// appendGrades will return the "head" (sometimes new, sometimes the same old one)
GradeNode * appendGrades (GradeNode *head, int s){
// just add this to the end of the appendGrades function:
return head;

就是这样。您也可以更改buildStudentList函数以遵守此设计,并始终返回学生链表的头(有时是新的,有时是旧的)。我相信这会更好、更有用,特别是在您稍后遇到的更复杂的问题/任务中。