I've started learning C++ and still making my first program. This is a continuation of my last post.
My original aim was to make a linked list at a professional level. But have now changed it to a doubly linked list, to simplify the code. It implements a couple of public functions that should increase the usability of the list significantly.
I also tried to implement an internal iterator. But didn't see a benefit to making a bidirectional iterator, for internal use, to replace getNode
.
Whilst I think I improved all problems mentioned in my last post. I mostly focused on implementing the sentinel. I don't think it's a sentinel, as it's doing more than just being my end condition. And so I'd love some feedback on my implementation. But any and all critiques are wanted.
#include <iostream>
template <class T>
class LinkedList {
private:
class Node {
public:
Node* next;
Node* prev;
T data;
// For the sentinal
Node(): data('\0'), prev(this), next(this) {}
Node(T data, Node* before)
: data(data) {
prev = before;
next = before->next;
prev->next = this;
next->prev = this;
}
~Node() {
prev->next = next;
next->prev = prev;
}
Node(Node const&) = delete;
Node& operator=(Node const&) = delete;
};
Node sentinal;
Node* getNode(int index) {
if (index >= 0) {
int i = 0;
for (Node* node = sentinal.next; node != &sentinal; node = node->next) {
if (i == index) {
return node;
}
i++;
}
} else {
int i = -1;
for (Node* node = sentinal.prev; node != &sentinal; node = node->prev) {
if (i == index) {
return node;
}
i--;
}
}
throw std::out_of_range("List doesn't contain that item.");
}
public:
LinkedList() {}
~LinkedList() {
clear();
}
LinkedList(LinkedList const&) = delete;
LinkedList& operator=(LinkedList const&) = delete;
void clear() {
while (sentinal.next != &sentinal) {
delete sentinal.next;
}
}
int length() {
int length = 0;
for (Node* node = sentinal.next; node != &sentinal; node = node->next) {
length += 1;
}
return length;
}
void append(T data) {
new Node(data, sentinal.prev);
}
T get(int index) {
return getNode(index)->data;
}
void insert(T data, int index) {
new Node(data, getNode(index)->prev);
}
T pop(int index=-1) {
Node* node = getNode(index);
T data = node->data;
delete node;
return data;
}
};
int main() {
LinkedList<char> list;
list.append('h');
list.append('l');
list.append('l');
list.append('l');
list.append('o');
list.insert('e', 1);
std::cout << list.pop(2) << list.get(-1) << '\n';
for (int i=0; i < list.length(); i++) {
std::cout << list.get(i);
}
std::cout << '\n';
list.clear();
std::cout << list.length() << '\n';
}