#ifndef ALREADY_INCLUDED_LIST_HH
#define ALREADY_INCLUDED_LIST_HH
#include "../noio/io.hh"
#define for_list(X,cursor,mylist) for (Node<X>* cursor=(mylist)->get_first(); cursor != null; cursor=cursor->get_next())
#define for_list_const(X,cursor,mylist) for (const Node<X>* cursor=(mylist)->get_first_const(); cursor != null; cursor=cursor->get_next_const())
#define for_list_backwards(X,cursor,mylist) for (Node<X>* cursor=(mylist)->get_last(); cursor != null; cursor=cursor->get_previous())
#define for_list_backwards_const(X,cursor,mylist) for (const Node<X>* cursor=(mylist)->get_last_const(); cursor != null; cursor=cursor->get_previous_const())
template<class X>
class Node;
template<class X>
class List
{
friend class Node<X>;
private:
Node<X>* private_first;
Node<X>* private_last;
int private_length;
bool private_dirty;
private:
List(const List&);
List& operator = (const List&);
public:
List()
{
private_first = null;
private_last = null;
private_length = 0;
private_dirty = false;
}
void delete_shallow()
{
if (this == null) {
return;
}
assert(this != null);
Node<X>* n_next;
for (Node<X>* n = private_first; n != null; n=n_next) {
n_next = n->private_next;
delete n;
}
private_length = 0;
private_dirty = true;
}
void delete_deep()
{
if (this == null) {
return;
}
assert(this != null);
Node<X>* n_next;
for (Node<X>* n = private_first; n != null; n=n_next) {
n_next = n->private_next;
delete n->private_data;
delete n;
}
private_length = 0;
private_dirty = true;
}
virtual ~List()
{
delete_shallow();
}
Node<X>* get_first()
{
ASSERT(this != null);
private_dirty = true;
return private_first;
}
Node<X>* get_last()
{
ASSERT(this != null);
private_dirty = true;
return private_last;
}
const Node<X>* get_first_const() const
{
ASSERT(this != null);
return private_first;
}
const Node<X>* get_last_const() const
{
ASSERT(this != null);
return private_last;
}
int get_length() const
{
ASSERT(this != null);
return private_length;
}
bool get_dirty() const
{
ASSERT(this != null);
return private_dirty;
}
void clear_dirty()
{
ASSERT(this != null);
private_dirty = false;
}
void add_to_start(X* x)
{
ASSERT(this != null);
Node<X>* n = new Node<X>();
n->private_data = x;
n->private_next = private_first;
n->private_previous = null;
n->private_owner = this;
if (private_first != null) {
private_first->private_previous = n;
}
private_first = n;
if (private_last == null) {
private_last = n;
}
private_length++;
private_dirty = true;
}
void add_to_end(X* x)
{
ASSERT(this != null);
Node<X>* n = new Node<X>();
n->private_data = x;
n->private_next = null;
n->private_previous = private_last;
n->private_owner = this;
if (private_last != null) {
private_last->private_next = n;
}
if (private_first == null) {
private_first = n;
}
private_last = n;
private_length++;
private_dirty = true;
}
void reverse()
{
ASSERT(this != null);
Node<X>* n_next = null;
for (Node<X>* n = private_first; n != null; n=n_next) {
n_next = n->get_next();
Node<X>* tmp = n->private_previous;
n->private_previous = n->private_next;
n->private_next = tmp;
}
Node<X>* tmp = private_first;
private_first = private_last;
private_last = tmp;
private_dirty = true;
}
void add_list(List<X>* mylist)
{
ASSERT(this != null);
ASSERT(mylist != null);
for_list (X,n,mylist) {
add_to_end(n);
}
}
void add_element(X* x)
{
ASSERT(this != null);
add_to_end(x);
}
void add_element(Node<X>* node)
{
ASSERT(this != null);
ASSERT(node != null);
add_to_end(node->get_data());
}
void add_to_start(Node<X>* node)
{
ASSERT(this != null);
ASSERT(node != null);
add_to_start(node->get_data());
}
void add_to_end(Node<X>* node)
{
ASSERT(this != null);
ASSERT(node != null);
add_to_end(node->get_data());
}
};
template<class X>
class Node
{
friend class List<X>;
private:
X* private_data;
Node* private_next;
Node* private_previous;
List<X>* private_owner;
private:
Node& operator = (const Node&);
Node(const Node&);
private:
Node()
{
constructor_worker();
}
public:
~Node()
{
destructor_worker();
}
private:
void constructor_worker()
{
ASSERT(this != null);
private_data = null;
private_next = null;
private_previous = null;
private_owner = null;
}
private:
void destructor_worker()
{
if (this == null) {
return;
}
if (private_next != null) {
private_next->private_previous = private_previous;
}
if (private_previous != null) {
private_previous->private_next = private_next;
}
ASSERT(private_owner != null);
if (private_owner->private_first == this) {
private_owner->private_first =
private_owner->private_first->private_next;
}
if (private_owner->private_last == this) {
private_owner->private_last =
private_owner->private_last->private_previous;
}
private_owner->private_length--;
private_owner->private_dirty = true;
{
private_data = null;
private_next = null;
private_previous = null;
private_owner = null;
}
}
public:
X* get_data()
{
ASSERT(this != null);
ASSERT(private_owner != null);
private_owner->private_dirty = true;
return private_data;
}
void set_data(X* x)
{
ASSERT(this != null);
ASSERT(private_owner != null);
private_owner->private_dirty = true;
private_data = x;
}
Node* get_next()
{
ASSERT(this != null);
ASSERT(private_owner != null);
private_owner->private_dirty = true;
return private_next;
}
Node* get_previous()
{
ASSERT(this != null);
ASSERT(private_owner != null);
private_owner->private_dirty = true;
return private_previous;
}
List<X>* get_owner()
{
ASSERT(this != null);
ASSERT(private_owner != null);
private_owner->private_dirty = true;
return private_owner;
}
const X* get_data_const() const
{
ASSERT(this != null);
return private_data;
}
const Node* get_next_const() const
{
ASSERT(this != null);
return private_next;
}
const Node* get_previous_const() const
{
ASSERT(this != null);
return private_previous;
}
const List<X>* get_owner_const() const
{
ASSERT(this != null);
return private_owner;
}
void add_before_current(X* x)
{
ASSERT(this != null);
Node* n = new Node<X>();
n->private_data = x;
n->private_next = this;
n->private_previous = this->private_previous;
n->private_owner = this->private_owner;
if (n->private_next != null) {
n->private_next->private_previous = n;
}
if (n->private_previous != null) {
n->private_previous->private_next = n;
}
if (n->private_owner->private_first == this) {
n->private_owner->private_first = n;
}
n->private_owner->private_length++;
private_owner->private_dirty = true;
}
void add_after_current(X* x)
{
ASSERT(this != null);
Node* n = new Node<X>();
n->private_data = x;
n->private_next = this->private_next;
n->private_previous = this;
n->private_owner = this->private_owner;
if (n->private_next != null) {
n->private_next->private_previous = n;
}
if (n->private_previous != null) {
n->private_previous->private_next = n;
}
if (n->private_owner->private_last == this) {
n->private_owner->private_last = n;
}
n->private_owner->private_length++;
private_owner->private_dirty = true;
}
void add_after_current(Node<X>* node)
{
ASSERT(this != null);
ASSERT(node != null);
add_after_current(node->get_data());
}
void add_before_current(Node<X>* node)
{
ASSERT(this != null);
ASSERT(node != null);
add_before_current(node->get_data());
}
};
#define LIST_HH_CHECK_FOR_INDEX_OUT_OF_RANGE() \
ASSERT_INFO((index >= 0) && (index < mylist->get_length()), \
(string() + "List index out of bounds (0.." + (mylist->get_length()-1) + ") index=" + index)) \
template<class X>
class List_Extra
{
private:
List_Extra& operator = (List_Extra&);
List_Extra(const List_Extra&);
public:
friend int get_index(const Node<X>* node)
{
ASSERT(node != null);
const List<X>* mylist = node->get_owner_const();
ASSERT(mylist != null);
int count = 0;
for_list_const (X,n,mylist) {
if (n == node) {
return count;
}
count++;
}
cout << "\n*** This line should never get executed.\n";
ASSERT(false);
}
friend Node<X>* get_element_at(List<X>* mylist, int index)
{
ASSERT(mylist != null);
LIST_HH_CHECK_FOR_INDEX_OUT_OF_RANGE();
if (index <= mylist->get_length() / 2) {
int count=0;
for_list (X,n,mylist) {
if (count == index) {
ASSERT(mylist->get_dirty() == true);
return n;
}
count++;
}
} else {
int count = mylist->get_length()-1;
for_list_backwards (X,n,mylist) {
if (count == index) {
return n;
}
count--;
}
}
cout << "\n*** This line should never get executed.\n";
ASSERT(false);
}
friend const Node<X>* get_element_at_const(const List<X>* mylist, int index)
{
ASSERT(mylist != null);
LIST_HH_CHECK_FOR_INDEX_OUT_OF_RANGE();
if (index <= mylist->get_length() / 2) {
int count=0;
for_list_const (X,n,mylist) {
if (count == index) {
return n;
}
count++;
}
} else {
int count = mylist->get_length()-1;
for_list_backwards_const (X,n,mylist) {
if (count == index) {
return n;
}
count--;
}
}
cout << "\n*** this line should never get executed\n";
ASSERT(false);
}
friend void set_element_at(List<X>* mylist, int index, X* x)
{
ASSERT(mylist != null);
LIST_HH_CHECK_FOR_INDEX_OUT_OF_RANGE();
get_element_at(mylist,index)->set_data(x);
}
friend void set_element_at(List<X>* mylist, int index, Node<X>* node)
{
ASSERT(mylist != null);
ASSERT(node != null);
LIST_HH_CHECK_FOR_INDEX_OUT_OF_RANGE();
set_element_at(mylist, index, node->get_data());
}
friend Node<X>* find_element_eq(Node<X>* start, const X* element)
{
for (Node<X>* n = start; n != null; n = n->get_next()) {
if (n->get_data() == element) {
return n;
}
}
return null;
}
friend const Node<X>* find_element_eq_const(const Node<X>* start,
const X* element)
{
for (const Node<X>* n = start; n != null; n = n->get_next_const()) {
if (n->get_data_const() == element) {
return n;
}
}
return null;
}
friend List<X>* clone_shallow(List<X>* mylist)
{
List<X>* result = new List<X>;
for_list (X,n,mylist) {
X* x = n->get_data();
result->add_to_end(x);
}
return result;
}
friend void delete_duplicates_eq(List<X>* mylist)
{
ASSERT(mylist != null);
for_list (X, n1, mylist) {
for_list (X, n2, mylist) {
if (n1 < n2) {
if (n1->get_data() != null) {
if (n1->get_data() == n2->get_data()) {
n2->set_data(null);
}
}
}
}
}
Node<X>* n_next;
for (Node<X>* n = mylist->get_first(); n != null; n=n_next) {
n_next = n->get_next();
if (n->get_data() == null) {
delete n;
}
}
}
friend void quicksort(List<X>* mylist, bool (*is_less_than)(const X* x1, const X* x2))
{
if (mylist->get_length() < 2) {
return;
}
X* mid = get_element_at(mylist,mylist->get_length() / 2)->get_data();
List<X>* smaller_than = new List<X>();
List<X>* equal_to = new List<X>();
List<X>* greater_than = new List<X>();
{
for_list (X, n, mylist) {
X* t = n->get_data();
if (is_less_than(t, mid)) {
smaller_than->add_element(t);
} else if (is_less_than(mid,t)) {
greater_than->add_element(t);
} else {
assert(!is_less_than(t,mid));
assert(!is_less_than(mid,t));
equal_to->add_element(t);
}
}
mylist->delete_shallow();
}
{
if (smaller_than->get_length() > 1) {
quicksort(smaller_than, is_less_than);
}
if (greater_than->get_length() > 1) {
quicksort(greater_than, is_less_than);
}
}
{
for_list (X,n,smaller_than) {
mylist->add_element(n);
}
delete smaller_than;
for_list (X,n,equal_to) {
mylist->add_element(n);
}
delete equal_to;
for_list (X,n,greater_than) {
mylist->add_element(n);
}
delete greater_than;
}
}
friend bool is_empty(const List<X>* mylist)
{
ASSERT(mylist != null);
return mylist->get_length() == 0;
}
friend Node<X>* get_second(List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 2);
return mylist->get_first()->get_next();
}
friend Node<X>* get_third(List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 3);
return mylist->get_first()->get_next()->get_next();
}
friend const Node<X>* get_second_const(const List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 2);
return mylist->get_first_const()->get_next_const();
}
friend const Node<X>* get_third_const(const List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 3);
return mylist->get_first_const()->get_next_const()->get_next_const();
}
friend Node<X>* get_second_to_last(List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 2);
return mylist->get_last()->get_previous();
}
friend Node<X>* get_third_to_last(List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 3);
return mylist->get_last()->get_previous()->get_previous();
}
friend const Node<X>* get_second_to_last_const(const List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 2);
return mylist->get_last_const()->get_previous_const();
}
friend const Node<X>* get_third_to_last_const(const List<X>* mylist)
{
ASSERT(mylist != null);
ASSERT(mylist->get_length() >= 3);
return mylist->get_last_const()->get_previous_const()->get_previous_const();
}
friend bool is_first(const Node<X>* node)
{
ASSERT(node != null);
return node->get_previous_const() == null;
}
friend bool is_last(const Node<X>* node)
{
ASSERT(node != null);
return node->get_next_const() == null;
}
friend Node<X>* get_cyclic_next(Node<X>* node)
{
ASSERT(node != null);
if (node->get_next() != null) {
ASSERT(node->get_owner()->get_dirty() == true);
return node->get_next();
}
else {
ASSERT(node->get_owner()->get_dirty() == true);
return node->get_owner()->get_first();
}
}
friend const Node<X>* get_cyclic_next_const(const Node<X>* node)
{
ASSERT(node != null);
if (node->get_next_const() != null) {
return node->get_next_const();
}
else {
return node->get_owner_const()->get_first_const();
}
}
friend Node<X>* get_cyclic_previous(Node<X>* node)
{
ASSERT(node != null);
if (node->get_previous() != null) {
ASSERT(node->get_owner()->get_dirty() == true);
return node->get_previous();
}
else {
ASSERT(node->get_owner()->get_dirty() == true);
return node->get_owner()->get_last();
}
}
friend const Node<X>* get_cyclic_previous_const(const Node<X>* node)
{
ASSERT(node != null);
if (node->get_previous_const() != null) {
return node->get_previous_const();
}
else {
return node->get_owner_const()->get_last_const();
}
}
};
class Reader;
class Writer;
template<class X>
class List_Io
{
private:
List_Io& operator = (List_Io&);
List_Io(const List_Io&);
public:
friend Writer& operator << (Writer& w, const Node<X>& node)
{
if (&node == null || node.get_data_const() == null) {
w << "null";
} else {
w << *node.get_data_const();
}
return w;
}
friend Writer& operator << (Writer& w, const List<X>& mylist)
{
if (&mylist == null) {
w << "null";
} else {
w << '(' << get_class_name(&mylist);
for_list_const (X,n,&mylist) {
w << ' ' << *n;
}
w << ')';
}
return w;
}
friend Reader& operator >> (Reader& r, List<X>& mylist)
{
ASSERT(&mylist != null);
ASSERT(mylist.get_length() == 0);
r >> '(' >> get_class_name(&mylist);
while (!r.looking_at(')')) {
if (r.looking_at("null")) {
X* x = null;
mylist.add_to_end(x);
r >> "null";
} else {
X* x = new X();
r >> *x;
mylist.add_to_end(x);
}
}
r >> ')';
return r;
}
friend void OK(const List<X>* mylist)
{
if (mylist == null) {
return;
}
string_buffer message;
bool was_error = false;
{
if (mylist->get_first_const() == null) {
} else {
if (mylist->get_first_const()->get_previous_const() != null) {
message << "\n*** OK failed\n";
message << "private_first->private_previous != null";
}
}
}
{
if (mylist->get_last_const() == null) {
} else {
if (mylist->get_last_const()->get_next_const() != null) {
message << "\n*** OK failed\n";
message << "private_last->private_next != null";
}
}
}
{
const Node<X>* n = mylist->get_first_const();
if (n != null) {
for (; n->get_next_const() != null; n=n->get_next_const()) {
}
if (n != mylist->get_last_const()) {
message << "\n*** OK failed\n";
message << "Calculated last (" << *n << ") ";
message << "does not agree with last element of list (";
message << *mylist->get_last_const() << ")";
was_error = true;
}
}
}
{
const Node<X>* n = mylist->get_last_const();
if (n != null) {
for (; n->get_previous_const() != null; n=n->get_previous_const()) {
}
if (n != mylist->get_first_const()) {
message << "\n*** OK failed\n";
message << "Calculated first (" << *n << ") ";
message << "does not agree with first element of list (";
message << *mylist->get_first_const() << ")";
was_error = true;
}
}
}
{
bool ok = true;
for_list_const (X,n,mylist) {
if (n->get_owner_const() != mylist) {
ok = false;
break;
}
}
for_list_backwards_const (X,n,mylist) {
if (n->get_owner_const() != mylist) {
ok = false;
break;
}
}
if (!ok) {
message << "\n*** OK failed\n";
message << "Some list element(s) do not have the correct owner field!";
was_error = true;
}
}
{
int calculated_length_forward = 0;
for_list_const (X,nn,mylist) {
calculated_length_forward++;
}
if (calculated_length_forward != mylist->get_length()) {
message << "\n*** OK failed\n";
message << "Calculated length forward (" << calculated_length_forward << ") ";
message << "does not match list length (" << mylist->get_length() << ")";
was_error = true;
}
}
{
int calculated_length_backward = 0;
for_list_backwards_const (X,nn,mylist) {
calculated_length_backward++;
}
if (calculated_length_backward != mylist->get_length()) {
message << "\n*** OK failed\n";
message << "Calculated length backward (" << calculated_length_backward << ") ";
message << "does not match list length (" << mylist->get_length() << ")";
was_error = true;
}
}
if (was_error) {
message << "\n\nHere is the list: " << *mylist << endl;
}
ASSERT_INFO(!was_error, message);
}
};
template<class X>
class List_Operator_Ee
{
private:
List_Operator_Ee& operator = (List_Operator_Ee&);
List_Operator_Ee(const List_Operator_Ee&);
public:
static bool xs_equal(const X* x1, const X* x2)
{
if ((x1 == null) && (x2 == null)) {
return true;
} else if ((x1 == null) || (x2 == null)) {
return false;
} else {
return *x1 == *x2;
}
}
friend bool operator == (const List<X>& list1, const List<X>& list2)
{
if ((&list1 == null) && (&list2 == null)) {
return true;
} else if ((&list1 == null) || (&list2 == null)) {
return false;
}
const Node<X>* n1 = list1.get_first_const();
const Node<X>* n2 = list2.get_first_const();
for ( ; ; ) {
if ((n1 == null) && (n2 == null)) {
return true;
}
if ((n1 == null) || (n2 == null)) {
return false;
}
if (!xs_equal(n1->get_data_const(), n2->get_data_const())) {
return false;
}
n1 = n1->get_next_const();
n2 = n2->get_next_const();
}
return true;
}
friend bool operator != (const List<X>& list1, const List<X>& list2)
{
return !(list1 == list2);
}
friend bool lists_equal(const List<X>* list1, const List<X>* list2)
{
return *list1 == *list2;
}
friend Node<X>* find_element_equal(Node<X>* start, const X& element)
{
for (Node<X>* n = start; n != null; n = n->get_next()) {
if (xs_equal(n->get_data(), &element)) {
return n;
}
}
return null;
}
friend const Node<X>* find_element_equal_const(const Node<X>* start, const X& element)
{
for (const Node<X>* n = start; n != null; n = n->get_next_const()) {
if (xs_equal(n->get_data_const(), &element)) {
return n;
}
}
return null;
}
friend void delete_duplicates_equal(List<X>* mylist)
{
ASSERT(mylist != null);
for_list (X, n1, mylist) {
for_list (X, n2, mylist) {
if (n1 < n2) {
if (xs_equal(n1->get_data(), n2->get_data())) {
n2->set_data(null);
}
}
}
}
Node<X>* n_next;
for (Node<X>* n = mylist->get_first(); n != null; n=n_next) {
n_next = n->get_next();
if (n->get_data() == null) {
delete n;
}
}
}
friend void delete_duplicates_equal_deep(List<X>* mylist)
{
ASSERT(mylist != null);
for_list (X, n1, mylist) {
for_list (X, n2, mylist) {
if (n1 < n2) {
if (xs_equal(n1->get_data(), n2->get_data())) {
delete n2->get_data();
n2->set_data(null);
}
}
}
}
Node<X>* n_next;
for (Node<X>* n = mylist->get_first(); n != null; n=n_next) {
n_next = n->get_next();
if (n->get_data() == null) {
delete n;
}
}
}
};
template<class X>
class List_Clone
{
friend void add_element_deep(List<X>* accumulator, const X* x)
{
ASSERT(accumulator != null);
ASSERT(x != null);
X* xx = clone(*x);
accumulator->add_to_end(xx);
}
friend void add_list_deep(List<X>* accumulator, const List<X>* adder)
{
ASSERT(accumulator != null);
if (adder != null) {
for_list_const (X,n,adder) {
add_element_deep(accumulator, n->get_data_const());
}
}
}
friend List<X>* clone_deep(const List<X>* mylist)
{
ASSERT(mylist != null);
List<X>* result = new List<X>;
add_list_deep(result, mylist);
return result;
}
};
#endif