Storing information in separate Linked Lists

I have a list of names of employees and number of skills, along with the name of the skills and its corresponding years of experience. The employee names and number of skills are stored in a struct that has a link to another Skills Node, where the skill name and skill years are stored.
This is the txt file:
1
2
3
Mary	3 networking 	 10	sewing	5	fishing 3
Jimmy	2 sleeping	15	talking	20 
Joseph	0


This code below currently puts all the skills in one big Skill node. How would I be able to store the skills in a separate linked list for each employee so I can print all skills for a name entered by the user?

The Skill struct:
1
2
3
4
5
6
7
8
9
    struct Skill {
       string name;
       int years;
    };

    struct Node {
       Skill data;
       Node * next;
    };


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    #include <iostream>
    #include <fstream>

    using namespace std;

    #include "Skill.h"

    struct Emp{
    string fname;
    int num;
    Node *top;
    };

                Node * createNode (string skill_name, int skill_years){
                    Node *newNode;
                    newNode= new Node;

                    newNode->data.name=skill_name;
                    newNode->data.years=skill_years;

                    newNode->next==NULL;
                    return newNode;
                }

                Node * insertAtHead (Node * top, string skill_name, int skill_years){
                    Node *newNode;
                    newNode=createNode(skill_name, skill_years);

                    newNode->next=top;
                    top=newNode;

                    return top;
                }


                bool contains (Node * top, string key){
                    if(top==NULL)
                        return false;
                    if(top->data.name==key)
                        return true;

                    return contains(top->next, key);
                }

                int size (Node * top){
                    if(top==NULL)
                        return 0;

                    return 1+size(top->next);
                }

                void printList (Node * top) {
                   Node * curr;

                   curr = top;
                   while (curr != NULL) {
                      cout << curr->data.name<<", "<< curr->data.years << endl;
                      curr = curr->next;
                   }
                }


                int main() {

                    ifstream in;
                    in.open("Employees.txt");

                    Emp e[30];
                    Skill s;

                    string skill="";

                    int year=0;
                    int count=0;
                    int option=0;
                    int i=0;
                    int len=0;

                    Node *top;
                    top = NULL;

                    printMenu();
                    cin>>option;

                    

                    if(option==1){
                        in>>e[i].fname;

                        while(e[i].fname!="END"){
                            in>>e[i].num;

                            cout<<e[i].fname<<" - "<<e[i].num<<endl;

                            count=0;
                                while(count!=e[i].num){
                                    in>>skill>>year;
                                    top=insertAtHead(top, skill, year);
                                    count++;
                                }
                                printList(top);

                            cout<<endl;

                            i++;
                            in>>e[i].fname;
                        }

                        cout<<"Data read"<<endl;
                    }

                }
Last edited on
Why lists, when you can have map of maps?
1
2
3
4
5
6
7
8
9
10
11
12
13
using Skills = std::map<std::string,int>;
std::map<std::string,Skills> employees;

// fill employees

// show:
for ( const auto& emp : employees ) {
  std::cout << emp.first << '\t' << emp.second.size();
  for ( const auto& skill : emp.second ) {
    std::cout << ' ' << skill.first << ' ' << skill.second;
  }
  std::cout << '\n';
}
I'm using this method to further learn about Linked Lists and arrays & later experiment with binary search. Haven't gotten to maps.
[EDIT]
Basically, the info is in the linked list but I'm trying to have them so each employee has their own linked list of skills, instead of the the previous employee's skills stacking onto the first batch.

1
2
3
4
5
6
    count=0;
    while(count!=e[i].num){
            in>>skill>>year;
            top=insertAtHead(top, skill, year);
            count++;
             }


I'm thinking the way to fix this might be to have top point to the next node but that's where I'm stuck
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
struct Emp{
  string fname;
  int num;
  Node top;
};

Node* insertAtHead( Node*, string, int );

// ...

Emp e;
Node *top;
top = NULL;

Each Emp has a Node. You never use it. You refer to your list(s) with pointer 'top' that has nothing to do with any Emp.
Each Emp could have a pointer to the first Node of that Emp (if any).
Last edited on
I've just realized I forgot the pointer to top in the struct, so I've made that change. But how would I implement that solution?
1
2
3
4
5
struct Emp{
  string fname;
  int num;
  Node *top;    //EDIT
};


Last edited on
You need two linked lists, one for the Employees and one for the Skills. Although the number of skills is specified in the input file, you don't need to store it. I'll add a constructor, as it'll make things easier later on.

A node in the Skills list might look like:
1
2
3
4
5
6
7
struct SkillNode {
    SkillNode() : next(nullptr), experience(0) {}

    SkillNode* next;
    std::string name;
    unsigned experience;
};


And a node in the Employee list might look like:
1
2
3
4
5
6
7
struct EmployeeNode {
    EmployeeNode() : next(nullptr), skills(nullptr) {}

    EmployeeNode* next;
    std::string name;
    SkillNode* skills;
};


One of the things you might want to do is add and entry from you input data. So first you need to wrap all those nodes in a single entity that you can work with.
1
2
3
4
5
6
class Employees {
    EmployeeNode* head;

public:
    Employees() : head(nullptr) {}
};


Ok, back to what we wanna do with it, add entry from your input line:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void Employee::add(std::string line) {
    EmployeeNode* empNode = new EmployeeNode;

    // make an input stream from the line so we can parse it
    std::istringstream is(line);
    int n;
    is >> empNode->name >> n;
    for (int i = 0; i < n; ++i) {
        SkillsNode* skillsNode = new SkillsNode;
        is >> skillsNode->name >> skillsNode->experience;
        skillsNode->next = empNode->skills;
        empNode->skills = skillsNode;
    }

    // add the newly created EmployeeNode to the head of the list.
    empNode->next = head;
    head = empNode;
}


You'd add methods for the things you want to do with Employees to that class. Don't expose the program to nodes, that's an implementation detail.

Also, I've just typed this code into the page, I haven't tried to compile it. But I'm just demonstrating how you may consider doing it. So it may not compile, especially as I haven't shown the headers you'd need to include.
Ok, I see you created a new Node, I tried it and it worked, thank you
Topic archived. No new replies allowed.