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

时间:2019-02-06 05:49:53

标签: c++ linked-list

伙计们,我的代码应该创建一个学生的链接列表,并且必须为每个学生创建该学生的成绩的链接列表。我无法真正确定两个链接列表是否设置正确,因为当我尝试遍历列表时不会打印任何成绩。

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

将成绩附加到链表中,头仍然不正常(该学生的成绩表头)

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

谢谢大家的投入!

1 个答案:

答案 0 :(得分:5)

最简单的解决方案是将GradeNode * headGradeNode *& head函数的签名中的buildGradeList更改为appendGrades。可以,但是我不建议您使用它,因为它错过了锻炼的重点。

您的代码对我来说似乎最正确(我还没有运行它,所以我不确定),除了一个问题:当您将成绩列表的开头传递给这两个函数时,就将它传递给了我按价值。这意味着将复制一个头部,并且您所做的所有更改都将被复制,这意味着它们不会生效,并且您学生的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函数以遵循此设计,并始终返回学生链接列表的头部(有时是新的,有时是相同的旧列表。)我相信这样做会更好,更有用,尤其是在更复杂的问题中/您以后会遇到的任务。

相关问题