patterncppMinor
Building a simple singly-linked list in C++11
Viewed 0 times
simplebuildingsinglylistlinked
Problem
The implementation below works, but I'm wondering if there's a modern C++ alternative.
For example:
Let me know if you see any other things I could improve. I know I could also use a class, but I'd like to understand how to do this with
For example:
- Should I replace the raw
newwith a braced initializer?
- Should I replace the
Node*with ashared_ptr?
Let me know if you see any other things I could improve. I know I could also use a class, but I'd like to understand how to do this with
struct.#include
struct Node {
int data;
Node* next;
};
void insert(Node*& head, int data) {
Node* new_node = new Node;
new_node->data = data;
new_node->next = head;
head = new_node;
}
void print_list(Node* list) {
Node* p {list};
std::cout data;
p = p->next;
while(p) {
std::cout " data;
p = p->next;
}
std::cout 10Solution
First, note that the only real difference between a
In any case, some of your code can be simplified somewhat. For example, your
It's usually better to initialize rather than construct something uninitialized, and then assign a value anyway, so this is sort of a double-win.
I'd also prefer to use a
In this case, I'd restructure the code a bit to treat the list being non-null as a pre-condition to
The next steps I can see would involve the sort of re-vamping you don't seem to want right now--turning the linked list into a full-blown class of its own that supports iterators and such. This does have a tremendous advantage though: right now, your linked list only supports inserting items, then printing an entire linked list. If anybody wants to do anything else, they need to implement it entirely on their own, and know all about the internal details of the linked list to do it.
Along with that, you'd probably want to make it a generic container, so you can use it to store any data type, not just
This way, you can immediately support essentially all code that knows how to work with a collection that supports (in this case) forward iterators. You'd probably just eliminate
This is (IMO) much cleaner in general. In particular, it separates concerns much more cleanly: the linked list can concentrate solely on linked-list "things", and not worry about things like I/O as it does now.
struct and a class is the default accessibility: in a class everything is private by default, and in a struct everything is public by default. That's literally the only difference between the two.In any case, some of your code can be simplified somewhat. For example, your
insert can be reduced to just this:void insert(Node*& head, int data) {
head = new Node{data, head};
}It's usually better to initialize rather than construct something uninitialized, and then assign a value anyway, so this is sort of a double-win.
I'd also prefer to use a
for loop to print the list, and just a new-line where you want to print a new-line:void print_list(Node* list) {
Node* p {list};
std::cout data;
for (p=p->next; p != nullptr; p=p->next)
std::cout " data;
}
std::cout << "\n";
}In this case, I'd restructure the code a bit to treat the list being non-null as a pre-condition to
print_list and enforce that up-front:void print_list(Node* list) {
if (list == nullptr)
return;
std::cout data;
for (Node *p{list->next}; p != nullptr; p=p->next)
std::cout " data;
std::cout << "\n";
}The next steps I can see would involve the sort of re-vamping you don't seem to want right now--turning the linked list into a full-blown class of its own that supports iterators and such. This does have a tremendous advantage though: right now, your linked list only supports inserting items, then printing an entire linked list. If anybody wants to do anything else, they need to implement it entirely on their own, and know all about the internal details of the linked list to do it.
Along with that, you'd probably want to make it a generic container, so you can use it to store any data type, not just
int.This way, you can immediately support essentially all code that knows how to work with a collection that supports (in this case) forward iterators. You'd probably just eliminate
print_list entirely, as it becomes just an application of std::copy from a list to (for example) an infix_iterator.This is (IMO) much cleaner in general. In particular, it separates concerns much more cleanly: the linked list can concentrate solely on linked-list "things", and not worry about things like I/O as it does now.
Code Snippets
void insert(Node*& head, int data) {
head = new Node{data, head};
}void print_list(Node* list) {
Node* p {list};
std::cout << "Printing list:\n";
if (p)
{
std::cout << p->data;
for (p=p->next; p != nullptr; p=p->next)
std::cout << " -> " << p->data;
}
std::cout << "\n";
}void print_list(Node* list) {
if (list == nullptr)
return;
std::cout << "Printing list:\n";
std::cout << list->data;
for (Node *p{list->next}; p != nullptr; p=p->next)
std::cout << " -> " << p->data;
std::cout << "\n";
}Context
StackExchange Code Review Q#129035, answer score: 5
Revisions (0)
No revisions yet.