#ifndef LIST_H_ #define LIST_H_ #include "ListNode.h" template class List{ private: ListNodePosi(T) head; ListNodePosi(T) tail; int size; protected:// internal methods ListNodePosi(T) selectMax(ListNodePosi(T) p, int n); void swap(T &one, T &two); public: //constructors List(); // empty List List(List const &L); // copy from another List List(List const &L, int rank, int n); // copy n elements from L[rank] List(ListNodePosi(T) p, int n); // copy n elements from position p //deconstructor ~List(); //read-only interfaces ListNodePosi(T) first() const { return head->succ; } ListNodePosi(T) last() const { return tail->prev; } ListNodePosi(T) prev(ListNodePosi(T) p) const { return p->prev == head? nullptr: p->prev; } ListNodePosi(T) next(ListNodePosi(T) p) const { return p->succ == tail? nullptr: p->succ; } ListNodePosi(T) find(T const &val) const { return find(val, size, tail); } //find val from all elements of the list ListNodePosi(T) find(T const &val, int n, ListNodePosi(T) p) const; //find val from a range of n elements before p ListNodePosi(T) search(T const &val, int n, ListNodePosi(T) p) const; //find val in a sorted List ListNodePosi(T) search(T const &val) const { return search(val, size, tail); } //find val universally in a sorted List T& operator[](int rank); int getSize() const { return size; } bool empty() const { return size == 0; } //writable interfaces //insert and delete operations ListNodePosi(T) push_back(T const &val); ListNodePosi(T) push_front(T const & val); ListNodePosi(T) insert_before(int rank, T const &val); ListNodePosi(T) insert_before(ListNodePosi(T) p, T const &val); ListNodePosi(T) pop_back(); ListNodePosi(T) pop_front(); ListNodePosi(T) pop(int rank); ListNodePosi(T) pop(ListNodePosi(T) p); //sort algorithms void selection_sort() { selection_sort(head->succ, size); } void selection_sort(ListNodePosi(T) p, int n); void insertion_sort() { insertion_sort(head->succ, size); } void insertion_sort(ListNodePosi(T) p, int n); //deduplicate & uniquify int deduplicate(); int uniquify(); }; /*----------implementations of class List----------*/ // internal methods template void List::swap(T &one, T &two){ T tmp = one; one = two; two = tmp; } template ListNodePosi(T) List::selectMax(ListNodePosi(T) p, int n){ ListNodePosi(T) maxPosi = p; while(--n){ p = p->succ; if (maxPosi->val <= p->val) maxPosi = p; } return maxPosi; } //constructors template List::List(){ tail = new ListNode(); head = new ListNode(); tail->prev = head; head->succ = tail; size = 0; } template List::List(List const &L) { tail = new ListNode(); head = new ListNode(); tail->prev = head; head->succ = tail; size = 0; ListNodePosi(T) p = L.head->succ; for (int ix = 0, size = L.getSize(); ix != size; ++ix, p = p->succ) push_back(p->val); } template List::List(List const &L, int rank, int n){ ListNodePosi(T) p = L.head->succ; while (rank--) p = p->succ; tail = new ListNode(); head = new ListNode(); tail->prev = head; head->succ = tail; size = 0; for (int ix = 0; ix != n; ++ix, p = p->succ) push_back(p->val); } template List::List(ListNodePosi(T) p, int n){ tail = new ListNode(); head = new ListNode(); tail->prev = head; head->succ = tail; size = 0; for (int ix = 0; ix != n; ++ix, p = p->succ) push_back(p->val); } //deconstructor template List::~List(){ while (size) pop_back(); } //read-only interfaces template ListNodePosi(T) List::find(T const &val, int n, ListNodePosi(T) p) const { while ((p = p->prev) != head && n--) if (p->val == val) return p; return nullptr; } template ListNodePosi(T) List::search(T const &val, int n, ListNodePosi(T) p) const{ for(int ix = 0; ix != n; ++ix){ p = p->prev; if (p->val <= val) return p; } return p->prev; } template T& List::operator[](int rank){ ListNodePosi(T) p = head->succ; while (rank--) p = p->succ; return p->val; } // writable interfaces //insert and delete operations template ListNodePosi(T) List::push_back(T const &val){ ++size; return tail->insertAsPred(val); } template ListNodePosi(T) List::push_front(T const &val) { ++size; return head->insertAsSucc(val); } template ListNodePosi(T) List::pop_back() { if (empty()) return nullptr; ListNodePosi(T) res = tail->prev; res->prev->succ = tail; tail->prev = res->prev; --size; return res; } template ListNodePosi(T) List::pop_front() { if (empty()) return nullptr; ListNodePosi(T) res = head->succ; head->succ = res->succ; res->succ->prev = head; --size; return res; } template ListNodePosi(T) List::insert_before(int rank, T const &val){ ListNodePosi(T) p = head->succ; while (rank--) p = p->succ; return insert_before(p, val); } template ListNodePosi(T) List::insert_before(ListNodePosi(T) p, T const &val){ ++size; return p->insertAsPred(val); } template ListNodePosi(T) List::pop(int rank){ if (rank >= size || rank < 0) return nullptr; ListNodePosi(T) p = head->succ; while (rank--) p = p->succ; return pop(p); } template ListNodePosi(T) List::pop(ListNodePosi(T) p){ p->prev->succ = p->succ; p->succ->prev = p->prev; --size; return p; } //sort algorithms template void List::selection_sort(ListNodePosi(T) p, int n){ ListNodePosi(T) currMax; ListNodePosi(T) tail = p; for (int ix = 0; ix != n; ++ix, tail = tail->succ); for (; n != 1; --n) { currMax = selectMax(p, n); swap(currMax->val, tail->prev->val); tail = tail->prev; } } template void List::insertion_sort(ListNodePosi(T) p, int n){ ListNodePosi(T) target; for(int ix = 1; ix != n; ix++){ p = p->succ; target = search(p->val, ix, p); insert_before(target->succ, p->val); pop(p); } } //deduplicate & uniquify //deduplicate & uniquify template int List::deduplicate() { int oldSize = size; ListNodePosi(T) p = head->succ; ListNodePosi(T) tmp; for (; p != tail; p = p->succ) { for (tmp = head->succ; tmp != p; tmp = tmp->succ) { if (tmp->val == p->val) { pop(tmp); break; } } } return oldSize - size; } template int List::uniquify(){ if (empty()) return 0; int oldSize = size; ListNodePosi(T) p = head->succ; while ((p = p->succ) != tail) if (p->val == p->prev->val) pop(p); return oldSize - size; } #endif