#include <iostream>
#include <memory>
/*
A singly linked list implemented in idiomatic modern C++.
Key ideas:
- Use a struct for the node
- Use std::unique_ptr for ownership (automatic memory management)
- Use raw pointers only for "next" traversal
- Provide push_front, push_back, print, and size operations
*/
class SinglyLinkedList {
private:
struct Node {
int value;
std::unique_ptr<Node> next;
Node(int v) : value(v), next(nullptr) {}
};
std::unique_ptr<Node> head; // Owns the first node
public:
SinglyLinkedList() = default;
// Insert at the front (O(1))
void push_front(int value) {
auto new_node = std::make_unique<Node>(value);
new_node->next = std::move(head);
head = std::move(new_node);
}
// Insert at the back (O(n))
void push_back(int value) {
auto new_node = std::make_unique<Node>(value);
if (!head) {
head = std::move(new_node);
return;
}
Node* cur = head.get();
while (cur->next) {
cur = cur->next.get();
}
cur->next = std::move(new_node);
}
// Print all values in the list
void print() const {
const Node* cur = head.get();
std::cout << "List: ";
while (cur) {
std::cout << cur->value << " ";
cur = cur->next.get();
}
std::cout << "\n";
}
// Count nodes (O(n))
std::size_t size() const {
std::size_t count = 0;
const Node* cur = head.get();
while (cur) {
++count;
cur = cur->next.get();
}
return count;
}
};
int main() {
SinglyLinkedList list;
list.push_front(3);
list.push_front(2);
list.push_front(1);
list.push_back(5);
list.push_back(4);
list.print();
std::cout << "Size: " << list.size() << "\n";
// No need to manually free memory — unique_ptr handles everything
}
/*
run:
List: 1 2 3 4 5
Size: 5
*/