Linked List Trouble

Dec 14, 2021 at 7:43am
I'm having trouble displaying this linked list I'm trying to build. I have 2 functions so far to append and print. But all it is returning is a single 0.

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
#include <iostream>

using namespace std;

struct LinkedList
{
	int value;
	LinkedList* next;
};

void append_node(LinkedList** head);
void printlist(LinkedList* head);
//void insert_node()

int main()
{
	//int num = 0;
	int nodes = 0;
	struct LinkedList* head = nullptr;
	cout << "How many do you want to input?  (Atleast one entry.) ";
	cin >> nodes;

	if (nodes < 1)
	{
		cout << "Enter a proper value: ";
		cin >> nodes;
	}

	for (int i = 0; i < nodes; i++)
		append_node(&head);

	cout << "Here is the updated linked list. \n";
	printlist(head);


	return 0;
}

void append_node(LinkedList** head)
{
	int num;
	cout << "Enter a number for a new node to enter to the end of list: ";
	cin >> num;

	LinkedList* Node = new LinkedList();

	if (*head == nullptr)
	{
		*head = Node;
		return;
	}

	Node->value = num;
	Node->next = nullptr;

	LinkedList* ptr = *head;
	while (ptr->next != nullptr)
	{
		ptr = ptr->next;
		ptr->next = Node;

	}
}

void printlist(LinkedList* ptr)
{
	//LinkedList* ptr = *head;
	while (ptr != nullptr)
	{
		cout << ptr->value << endl;
		ptr = ptr->next;
	}

}
Dec 14, 2021 at 8:08am
You need to refactor your code.

A linked list is the single, complete structure. However, you are using it for individual nodes. Start by calling your elemental struct a Node and not a LinkedList and you won't confuse everybody.

You shouldn't be sending the memory address of pointers - you end up double-dereferencing in append_ node. The whole point of pointers is that they already contain a memory address.

Start by refactoring your code.
Dec 14, 2021 at 8:35am
Your first problem is line 49. The member next is not set/invalid. Move line 53/54 before line 47.

Currently it is a mix of c and c++. With c++ you could write something like
1
2
3
4
5
struct LinkedList
{
	int value = 0;
	LinkedList* next = nullptr;
};
This would make it safer. Or even:
1
2
3
4
5
6
7
8
9
10
11
struct LinkedList
{
	int value = 0;
	LinkedList* next = nullptr;

LinkedList() = default;
LinkedList(int v) : value{v}
{
}

};
With this you can have this:
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
void append_node(LinkedList** head)
{
	int num;
	cout << "Enter a number for a new node to enter to the end of list: ";
	cin >> num;

	LinkedList* Node = new LinkedList(num);

	if (*head == nullptr)
	{
		*head = Node;
		return;
	}

	Node->value = num;
	Node->next = nullptr;

	LinkedList* ptr = *head;
	while (ptr->next != nullptr)
	{
		ptr = ptr->next;
		ptr->next = Node;

	}
}
Dec 14, 2021 at 10:24am
If this is not homework consider using std::list instead.
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
#include <iostream>
#include <list>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
	int nodes = 0, input = 0;
	list<int> my_list;

	cout << "How many do you want to input?  (At least one entry.) ";
	cin >> nodes;

	if (nodes < 1)
	{
		cout << "Enter a proper value: ";
		cin >> nodes;
	}

	for (int i = 0; i < nodes; i++)
	{
		cout << "Enter value " << i + 1 << ": ";
		std::cin >> input;
		my_list.push_back(input);
	}

	cout << "Here is the updated linked list. \n";
	copy(begin(my_list), end(my_list), ostream_iterator<int>(cout, " "));
}
Dec 15, 2021 at 12:10am
This is an assignment and he wanted us to build a certain way. I've took in the changes of setting the -> next = nullptr in struct declaration and also the new node after creation. Now the print function is only displaying the first node.
Dec 15, 2021 at 6:46am
Now the print function is only displaying the first node.
I recommend to use the debugger and go step by step through the code to unsterstand what happens. Or add debug cout.

1
2
3
4
5
6
7
	LinkedList* ptr = *head;
	while (ptr->next != nullptr)
	{
		ptr = ptr->next;
		ptr->next = Node;

	}
What happens the second time you call append_node(...)? Well, ptr->next will be nullptr. So the loop will never have any effect.

Consider this:
1
2
3
4
5
6
7
	LinkedList* last_ptr = nullptr;
	for(LinkedList* ptr = *head; ptr != nullptr; ptr = ptr->next)
	{
		last_ptr = ptr;
	}
	assert(last_ptr);
	last_ptr->next = Node;
Not tested!
Dec 15, 2021 at 10:05am
Perhaps:

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
#include <iostream>

struct LinkedList {
	int value {};
	LinkedList *next {};

	LinkedList() {};
	LinkedList(int v) : value {v} {}
};

void append_node(LinkedList** head);
void printlist(LinkedList* head);

int main() {
	size_t nodes {};
	LinkedList* head {};

	do {
		std::cout << "How many do you want to input? (At least one entry.): ";
		std::cin >> nodes;
	} while ((nodes < 1) && (std::cout << "Enter a proper value!\n"));

	for (size_t i = 0; i < nodes; ++i)
		append_node(&head);

	std::cout << "Here is the updated linked list. \n";
	printlist(head);
	std::cout << '\n';
}

void append_node(LinkedList** head) {
	int num {};

	std::cout << "Enter a number for a new node to add to the end of list: ";
	std::cin >> num;

	if (*head == nullptr)
		*head = new LinkedList(num);
	else {
		auto ptr{ *head };

		for (; ptr->next != nullptr; ptr = ptr->next);
		ptr->next = new LinkedList(num);
	}
}

void printlist(LinkedList* ptr) {
	for (; ptr != nullptr; ptr = ptr->next)
		std::cout << ptr->value << ' ';
}


Note that if nodes are added to the tail of a list, then it is common to also maintain a tail pointer as well as a head pointer. This allows direct tail insertion without L42 for loop. For large populated lists, this for loop on the performance can be significant.
Topic archived. No new replies allowed.