Skip to content

Instantly share code, notes, and snippets.

@scturtle
Last active September 10, 2022 17:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scturtle/f765962007ffaf3052b24818bb204a26 to your computer and use it in GitHub Desktop.
Save scturtle/f765962007ffaf3052b24818bb204a26 to your computer and use it in GitHub Desktop.
double linked list
#include <iostream>
struct ListNode {
void *m_prev = nullptr;
void *m_next = nullptr;
};
template <typename T> struct List {
private:
T *m_head = nullptr;
T *m_tail = nullptr;
inline ListNode &_node(T *obj) { return obj->m_listnode; }
public:
T *head() { return m_head; }
T *tail() { return m_tail; }
inline T *&prev(T *obj) { return (T *&)_node(obj).m_prev; }
inline T *&next(T *obj) { return (T *&)_node(obj).m_next; }
void add_before(T *pos, T *obj) {
next(obj) = pos;
if (pos) {
prev(obj) = prev(pos);
prev(pos) = obj;
} else {
prev(obj) = m_tail;
m_tail = obj;
}
if (prev(obj))
next(prev(obj)) = obj;
else
m_head = obj;
}
void add_after(T *pos, T *obj) {
prev(obj) = pos;
if (pos) {
next(obj) = next(pos);
next(pos) = obj;
} else {
next(obj) = m_head;
m_head = obj;
}
if (next(obj))
prev(next(obj)) = obj;
else
m_tail = obj;
}
T *remove(T *obj) {
if (!obj)
return nullptr;
if (prev(obj))
next(prev(obj)) = next(obj);
else
m_head = next(obj);
if (next(obj))
prev(next(obj)) = prev(obj);
else
m_tail = prev(obj);
prev(obj) = nullptr;
next(obj) = nullptr;
return obj;
}
void push_front(T *obj) { add_after(nullptr, obj); }
void push_back(T *obj) { add_before(nullptr, obj); }
T *pop_front() { return remove(m_head); }
T *pop_back() { return remove(m_tail); }
};
template <typename T, typename L>
void print(std::ostream &os, List<T> &l, L lambda) {
os << "[";
for (T *cur = l.head(); cur; cur = l.next(cur))
os << lambda(cur) << (l.next(cur) ? ", " : "");
os << "]\n";
}
struct MyInt {
int m_val;
ListNode m_listnode;
MyInt(int val) : m_val{val} {}
};
int main() {
List<MyInt> n;
auto a = new MyInt(1);
auto b = new MyInt(2);
auto c = new MyInt(3);
auto d = new MyInt(4);
n.push_front(b);
n.push_back(c);
n.push_front(a);
n.remove(b);
n.add_after(a, b);
n.remove(b);
n.add_before(c, b);
print(std::cout, n, [](MyInt *t) { return t->m_val; });
}
#include <cstdint>
#include <iostream>
struct ListNode {
ListNode *prev = nullptr;
ListNode *next = nullptr;
};
struct List {
ListNode *head = nullptr;
ListNode *tail = nullptr;
void add_before(ListNode *pos, ListNode *obj) {
obj->next = pos;
if (pos) {
obj->prev = pos->prev;
pos->prev = obj;
} else {
obj->prev = tail;
tail = obj;
}
if (obj->prev)
obj->prev->next = obj;
else
head = obj;
}
void add_after(ListNode *pos, ListNode *obj) {
obj->prev = pos;
if (pos) {
obj->next = pos->next;
pos->next = obj;
} else {
obj->next = head;
head = obj;
}
if (obj->next)
obj->next->prev = obj;
else
tail = obj;
}
ListNode *remove(ListNode *obj) {
if (!obj)
return nullptr;
if (obj->prev)
obj->prev->next = obj->next;
else
head = obj->next;
if (obj->next)
obj->next->prev = obj->prev;
else
tail = obj->prev;
obj->prev = nullptr;
obj->next = nullptr;
return obj;
}
void push_front(ListNode *obj) { add_after(nullptr, obj); }
void push_back(ListNode *obj) { add_before(nullptr, obj); }
ListNode *pop_front() { return remove(head); }
ListNode *pop_back() { return remove(tail); }
};
template <typename L> void print(std::ostream &os, const List &l, L lambda) {
os << "[";
for (ListNode *cur = l.head; cur; cur = cur->next)
os << lambda(cur) << (cur->next ? ", " : "");
os << "]\n";
}
template <typename T, typename U>
constexpr T *member_to_object(U T::*member, U *ptr) {
return (T *)((char *)ptr - (char *)&((T *)0->*member));
}
template <typename T> inline ListNode *to_node(T *obj) {
return obj ? &obj->m_listnode : nullptr;
}
template <typename T> inline T *to_object(ListNode *node) {
return node ? member_to_object(&T::m_listnode, node) : nullptr;
}
struct MyInt {
int m_val;
ListNode m_listnode;
MyInt(int val) : m_val{val} {}
};
int main() {
List l;
auto a = to_node(new MyInt(1));
auto b = to_node(new MyInt(2));
auto c = to_node(new MyInt(3));
auto d = to_node(new MyInt(4));
l.push_front(b);
l.push_back(c);
l.push_front(a);
l.remove(b);
l.add_after(a, b);
l.remove(b);
l.add_before(c, b);
print(std::cout, l, [](ListNode *t) { return to_object<MyInt>(t)->m_val; });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment