Skip to content

Instantly share code, notes, and snippets.

@mshafae
Last active April 26, 2024 20:37
Show Gist options
  • Save mshafae/102aefa38e3b28b83ad4357201e93d3a to your computer and use it in GitHub Desktop.
Save mshafae/102aefa38e3b28b83ad4357201e93d3a to your computer and use it in GitHub Desktop.
Doubly linked list using C style pointers.
// Gist https://gist.github.com/mshafae/102aefa38e3b28b83ad4357201e93d3a
// Filename list_with_c_ptr.cc
// CompileCommand clang++ -std=c++17 list_with_c_ptr.cc
// Doubly linked list using C style pointers.
#include <iostream>
class Printable {
public:
virtual void Print(std::ostream& out) = 0;
};
class Node : public Printable {
private:
int data_;
int id_;
Node* prev_;
Node* next_;
public:
Node(int data, int id, Node* prev, Node* next)
: data_{data}, id_{id}, prev_{prev}, next_{next} {
std::cerr << "Constructing: ";
Print(std::cerr);
std::cerr << "\n";
};
~Node() {
std::cerr << "\tDestroy: ";
Print(std::cerr);
std::cerr << "\n";
}
void Print(std::ostream& out) {
out << "Node(data = " << data_ << ", id = " << id_ << ", this = " << this
<< ", prev = " << prev_ << ", next = " << next_ << ")";
}
void Unlink() {
next_ = nullptr;
prev_ = nullptr;
}
void set_next(Node* next) { next_ = next; }
void set_previous(Node* prev) { prev_ = prev; }
Node* next() { return next_; }
Node* prev() { return prev_; }
int id() { return id_; }
};
class List : public Printable {
private:
Node* front_;
Node* back_;
int id_counter_;
public:
List() : front_{nullptr}, back_{nullptr}, id_counter_{0} {
std::cerr << "Constructing: ";
Print(std::cerr);
std::cerr << "\n";
}
~List() {
std::cerr << "Destroying:\n";
// List owns the nodes so it is responsible to delete the nodes.
Node* cursor = front_;
while (cursor != nullptr) {
std::cerr << "\t~List: ";
cursor->Print(std::cerr);
std::cerr << "\n";
Node* tmp_ptr = cursor;
cursor = cursor->next();
front_ = cursor;
tmp_ptr->Unlink();
delete tmp_ptr;
}
std::cerr << "\n";
}
void PushFront(int data) {
id_counter_++;
if (front_ == nullptr && back_ == nullptr) {
// empty
Node* new_node = new Node(data, id_counter_, nullptr, nullptr);
front_ = new_node;
back_ = new_node;
} else {
Node* new_node = new Node(data, id_counter_, nullptr, front_);
front_->set_previous(new_node);
front_ = new_node;
}
}
void PushBack(int data) {
id_counter_++;
if (front_ == nullptr && back_ == nullptr) {
// empty
Node* new_node = new Node(data, id_counter_, nullptr, nullptr);
front_ = new_node;
back_ = new_node;
} else {
Node* new_node = new Node(data, id_counter_, back_, nullptr);
back_->set_next(new_node);
back_ = new_node;
}
}
void Print(std::ostream& out) {
Node* cursor = front_;
std::cerr << "List contains:\n";
if (front_ == nullptr && back_ == nullptr) {
std::cerr << "\tempty\n";
return;
}
while (cursor != nullptr) {
std::cerr << "\t";
cursor->Print(std::cerr);
std::cerr << "\n";
cursor = cursor->next();
}
}
};
int main(int argc, char const* argv[]) {
List* l = new List();
for (int i = 0; i < 5; i++) {
l->PushFront(i + 10);
}
for (int i = 0; i < 5; i++) {
l->PushBack(i + 20);
}
std::cerr << "Printing l\n";
l->Print(std::cerr);
// Copy the pointer value, not move.
List* m = l;
l = nullptr;
std::cerr << "Printing m\n";
m->Print(std::cerr);
delete m;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment