600 lines
17 KiB
C++
600 lines
17 KiB
C++
#include <stdio.h>
|
|
|
|
template <class E> class Node {
|
|
private:
|
|
E content;
|
|
Node *nextNode;
|
|
|
|
public:
|
|
Node();
|
|
Node(E _content, Node<E> *_nextNode = NULL);
|
|
~Node();
|
|
// Returns a reference to the content.
|
|
E &getContent();
|
|
// Returns a reference to the next Node. May return NULL if this Node is the
|
|
// last one.
|
|
Node<E> *getNextPtr();
|
|
// Set the next Node _nextNode. Returns original pointer.
|
|
Node<E> *setNext(Node<E> *_nextNode);
|
|
// Returns a reference to the Tail.
|
|
Node<E> &getTail();
|
|
// Returns a reference to the Node of given index.
|
|
Node<E> &getByIndex(const int index);
|
|
// Compare the content with the argument.
|
|
bool operator==(const E &other);
|
|
// Destructs the Node itself and all the node behind it.
|
|
void destruct();
|
|
};
|
|
|
|
template <class E> class Iterator {
|
|
private:
|
|
Node<E> *current;
|
|
|
|
public:
|
|
Iterator(Node<E> *pos);
|
|
bool hasNext();
|
|
// Return the same as hasNext();
|
|
operator bool();
|
|
E &next();
|
|
E &peek();
|
|
Iterator<E> &insertHere(const E &_newItem);
|
|
};
|
|
|
|
template <class E> class List {
|
|
private:
|
|
Node<E> *head;
|
|
int _length;
|
|
// int getIndexInRange(int index) const;
|
|
// void quickSort(
|
|
// int leftBound, int rightBound,
|
|
// std::function<bool(const E &, const E &)> const &isCorrectOrderFunc);
|
|
|
|
public:
|
|
List();
|
|
List(const E &newItem);
|
|
List(const E *newItemList, const int itemCount);
|
|
List(const List<E> &otherList);
|
|
~List();
|
|
// Append _newItem at last. Returns the List itself.
|
|
List<E> &append(const E &_newItem);
|
|
// Insert _newItem at index, and move all items at and after [index] 1 step.
|
|
// Throws IndexError if index is not in the range of [-_length, _length -
|
|
// 1]. Returns the List itself.
|
|
List<E> &insert(int index, const E &_newItem);
|
|
// Pop the item at given index, default is the to pop the last one.
|
|
E pop(int index = -1);
|
|
// Remove the first occurance of target. Throws ValueError if target does
|
|
// not exist. Returns the List itself.
|
|
List<E> &remove(const E &target);
|
|
// List<E> &remove(std::function<bool(const E &)> const &isTargetFunc);
|
|
// Clear all nodes.
|
|
List<E> &clear();
|
|
// Swap the element located at index a and b. Throws IndexError if the given
|
|
// index is beyond length of the list.
|
|
List<E> &swap(int index_a, int index_b);
|
|
E &operator[](const int index);
|
|
const E &operator[](const int index) const;
|
|
List<E> &operator=(const List<E> &otherList);
|
|
|
|
int length() const;
|
|
bool contains(const E &target) const;
|
|
// bool contains(std::function<bool(const E &)> const &isTargetFunc) const;
|
|
// Give the index of target in the list on its first appearance. Throws
|
|
// ValueError if target does not exist.
|
|
int index(const E &target) const;
|
|
// int index(std::function<bool(const E &)> const &isTargetFunc) const;
|
|
// Give the reference to the target in the list on its first appearance.
|
|
// E &search(const E &target) const;
|
|
// E &search(std::function<bool(const E &)> const &isTargetFunc) const;
|
|
// Only retain item that matches the isTargetFunc
|
|
// List<E> &filter(std::function<bool(const E &)> const &isTargetFunc);
|
|
// Returns a new filtered list.
|
|
// const List<E>
|
|
// filtered(std::function<bool(const E &)> const &isTargetFunc) const;
|
|
// Sort this list.
|
|
// List<E> &
|
|
// sort(std::function<bool(const E &, const E &)> const
|
|
// &isCorrectOrderFunc);
|
|
// // Returns a sorted NEW list.
|
|
// const List<E> sorted(std::function<bool(const E &, const E &)> const
|
|
// &isCorrectOrderFunc) const;
|
|
Iterator<E> &&iterate();
|
|
Iterator<E> &&iterate(int index);
|
|
};
|
|
|
|
// template <class E>
|
|
// void List<E>::quickSort(
|
|
// int leftBound, int rightBound,
|
|
// std::function<bool(const E &, const E &)> const &isCorrectOrderFunc) {
|
|
// if (leftBound >= rightBound) {
|
|
// return;
|
|
// }
|
|
|
|
// int pivot = leftBound;
|
|
// int left = leftBound;
|
|
// int right = rightBound;
|
|
|
|
// while (left < right) {
|
|
// while (isCorrectOrderFunc((*this)[pivot], (*this)[right]) &&
|
|
// right > left) {
|
|
// right--;
|
|
// }
|
|
// this->swap(pivot, right);
|
|
// pivot = right;
|
|
|
|
// while (isCorrectOrderFunc((*this)[left], (*this)[pivot]) &&
|
|
// right > left) {
|
|
// left++;
|
|
// }
|
|
// this->swap(left, pivot);
|
|
// pivot = left;
|
|
// }
|
|
|
|
// quickSort(leftBound, pivot - 1, isCorrectOrderFunc);
|
|
// quickSort(pivot + 1, rightBound, isCorrectOrderFunc);
|
|
// }
|
|
|
|
template <class E> List<E>::List() : head(NULL), _length(0){};
|
|
|
|
template <class E>
|
|
List<E>::List(const E &newItem) : head(new Node<E>(newItem)), _length(1){};
|
|
|
|
template <class E> List<E>::List(const E *newItemList, const int itemCount) {
|
|
for (int i = 0; i < itemCount; i++) {
|
|
this->append(newItemList[i]);
|
|
}
|
|
};
|
|
|
|
template <class E> List<E>::List(const List<E> &otherList) {
|
|
if (otherList.length() > 0) {
|
|
this->head = new Node<E>(otherList[0]);
|
|
this->_length = 1;
|
|
Node<E> *nextPtr = otherList.head->getNextPtr();
|
|
while (nextPtr != NULL) {
|
|
this->append((*nextPtr).getContent());
|
|
nextPtr = (*nextPtr).getNextPtr();
|
|
}
|
|
}
|
|
else {
|
|
this->head = NULL;
|
|
this->_length = 0;
|
|
}
|
|
}
|
|
|
|
template <class E> List<E>::~List() {
|
|
if (this->head != NULL) {
|
|
this->head->destruct();
|
|
}
|
|
head = NULL;
|
|
}
|
|
|
|
template <class E> List<E> &List<E>::append(const E &_newItem) {
|
|
if (this->head == NULL) {
|
|
this->head = new Node<E>(_newItem);
|
|
}
|
|
else {
|
|
this->head->getTail().setNext(new Node<E>(_newItem));
|
|
}
|
|
this->_length++;
|
|
return *this;
|
|
}
|
|
|
|
template <class E> List<E> &List<E>::insert(int index, const E &_newItem) {
|
|
// if (index < 0) {
|
|
// index += this->_length;
|
|
// }
|
|
// if (index < 0 || index > _length) {
|
|
// throw(IndexError("Index not in range!"));
|
|
// }
|
|
if (index == 0) {
|
|
this->head = new Node<E>(_newItem, this->head);
|
|
}
|
|
else {
|
|
Node<E> &prev = this->head->getByIndex(index - 1);
|
|
prev.setNext(new Node<E>(_newItem, prev.getNextPtr()));
|
|
}
|
|
this->_length++;
|
|
return *this;
|
|
}
|
|
|
|
template <class E> List<E> &List<E>::remove(const E &target) {
|
|
this->pop(this->index(target));
|
|
return *this;
|
|
}
|
|
|
|
template <class E> E List<E>::pop(int index) {
|
|
// index = this->getIndexInRange(index);
|
|
|
|
Node<E> removed = this->head->getByIndex(index);
|
|
|
|
this->_length--;
|
|
if (index == 0) {
|
|
Node<E> *newHead = this->head->getNextPtr();
|
|
delete this->head;
|
|
this->head = newHead;
|
|
}
|
|
else {
|
|
Node<E> &prev = this->head->getByIndex(index - 1);
|
|
delete prev.getNextPtr();
|
|
prev.setNext(removed.getNextPtr());
|
|
}
|
|
return removed.getContent();
|
|
}
|
|
|
|
// template <class E>
|
|
// List<E> &List<E>::remove(std::function<bool(const E &)> const &isTargetFunc)
|
|
// {
|
|
// this->pop(this->index(isTargetFunc));
|
|
// return *this;
|
|
// }
|
|
|
|
template <class E> List<E> &List<E>::clear() {
|
|
if (this->_length == 0) {
|
|
return *this;
|
|
}
|
|
this->head->destruct();
|
|
this->head = NULL;
|
|
this->_length = 0;
|
|
return *this;
|
|
}
|
|
|
|
template <class E> List<E> &List<E>::swap(int index_a, int index_b) {
|
|
// index_a = this->getIndexInRange(index_a);
|
|
// index_b = this->getIndexInRange(index_b);
|
|
if (index_a == index_b) {
|
|
return *this;
|
|
}
|
|
|
|
Node<E> *tempPtr;
|
|
|
|
if (index_a == 0) {
|
|
if (index_b == 1) {
|
|
Node<E> &A = this->head->getByIndex(0);
|
|
Node<E> &B = this->head->getByIndex(1);
|
|
Node<E> *afterB = B.getNextPtr();
|
|
this->head = &B;
|
|
B.setNext(&A);
|
|
A.setNext(afterB);
|
|
}
|
|
else {
|
|
Node<E> &A = this->head->getByIndex(index_a);
|
|
Node<E> *afterA = A.getNextPtr();
|
|
Node<E> &beforeB = this->head->getByIndex(index_b - 1);
|
|
Node<E> &B = this->head->getByIndex(index_b);
|
|
Node<E> *afterB = B.getNextPtr();
|
|
|
|
this->head = &B;
|
|
beforeB.setNext(&A);
|
|
A.setNext(afterB);
|
|
B.setNext(afterA);
|
|
}
|
|
}
|
|
else {
|
|
if (index_b == index_a + 1) {
|
|
Node<E> &beforeA = this->head->getByIndex(index_a - 1);
|
|
Node<E> &A = beforeA.getByIndex(1);
|
|
Node<E> &B = A.getByIndex(1);
|
|
Node<E> *afterB = B.getNextPtr();
|
|
beforeA.setNext(&B);
|
|
B.setNext(&A);
|
|
A.setNext(afterB);
|
|
}
|
|
else {
|
|
Node<E> &beforeA = this->head->getByIndex(index_a - 1);
|
|
Node<E> &A = this->head->getByIndex(index_a);
|
|
Node<E> *afterA = A.getNextPtr();
|
|
Node<E> &beforeB = this->head->getByIndex(index_b - 1);
|
|
Node<E> &B = this->head->getByIndex(index_b);
|
|
Node<E> *afterB = B.getNextPtr();
|
|
|
|
beforeA.setNext(&B);
|
|
B.setNext(afterA);
|
|
beforeB.setNext(&A);
|
|
A.setNext(afterB);
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// template <class E>
|
|
// List<E> &List<E>::sort(
|
|
// std::function<bool(const E &, const E &)> const &isCorrectOrderFunc) {
|
|
// this->quickSort(0, this->_length - 1, isCorrectOrderFunc);
|
|
// return *this;
|
|
// }
|
|
|
|
template <class E> E &List<E>::operator[](const int index) {
|
|
// return this->head->getByIndex(getIndexInRange(index)).getContent();
|
|
return this->head->getByIndex(index).getContent();
|
|
}
|
|
|
|
template <class E> const E &List<E>::operator[](const int index) const {
|
|
// return this->head->getByIndex(getIndexInRange(index)).getContent();
|
|
return this->head->getByIndex(index).getContent();
|
|
}
|
|
|
|
template <class E> List<E> &List<E>::operator=(const List<E> &otherList) {
|
|
this->clear();
|
|
if (otherList.length() > 0) {
|
|
this->head = new Node<E>(otherList[0]);
|
|
this->_length = 1;
|
|
Node<E> *nextPtr = otherList.head->getNextPtr();
|
|
while (nextPtr != NULL) {
|
|
this->append((*nextPtr).getContent());
|
|
nextPtr = (*nextPtr).getNextPtr();
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class E> int List<E>::length() const {
|
|
return this->_length;
|
|
}
|
|
|
|
template <class E> bool List<E>::contains(const E &target) const {
|
|
if (this->_length == 0) {
|
|
return false;
|
|
}
|
|
|
|
Node<E> *current = this->head;
|
|
do {
|
|
if (current->getContent() == target) {
|
|
return true;
|
|
}
|
|
current = current->getNextPtr();
|
|
} while (current != NULL);
|
|
return false;
|
|
}
|
|
|
|
// template <class E>
|
|
// bool List<E>::contains(
|
|
// std::function<bool(const E &)> const &isTargetFunc) const {
|
|
// if (this->_length == 0) {
|
|
// return false;
|
|
// }
|
|
|
|
// Node<E> *current = this->head;
|
|
// do {
|
|
// if (isTargetFunc(current->getContent())) {
|
|
// return true;
|
|
// }
|
|
// current = current->getNextPtr();
|
|
// } while (current != NULL);
|
|
// return false;
|
|
// }
|
|
|
|
template <class E> int List<E>::index(const E &target) const {
|
|
Node<E> *nextPtr = this->head;
|
|
int pos = 0;
|
|
while (nextPtr != NULL) {
|
|
if (nextPtr->getContent() == target) {
|
|
return pos;
|
|
}
|
|
pos++;
|
|
nextPtr = nextPtr->getNextPtr();
|
|
}
|
|
// throw(ValueError("Target not found!"));
|
|
return -1;
|
|
}
|
|
|
|
// template <class E>
|
|
// int List<E>::index(std::function<bool(const E &)> const &isTargetFunc) const
|
|
// {
|
|
// Node<E> *nextPtr = this->head;
|
|
// int pos = 0;
|
|
// while (nextPtr != NULL) {
|
|
// if (isTargetFunc(nextPtr->getContent())) {
|
|
// return pos;
|
|
// }
|
|
// pos++;
|
|
// nextPtr = nextPtr->getNextPtr();
|
|
// }
|
|
// throw(ValueError("Target not found!"));
|
|
// }
|
|
|
|
// template <class E> E &List<E>::search(const E &target) const {
|
|
// Node<E> *nextPtr = this->head;
|
|
// while (nextPtr != NULL) {
|
|
// if (nextPtr->getContent() == target) {
|
|
// return nextPtr->getContent();
|
|
// }
|
|
// nextPtr = nextPtr->getNextPtr();
|
|
// }
|
|
// throw(ValueError("Target not found!"));
|
|
// }
|
|
|
|
// template <class E>
|
|
// E &List<E>::search(std::function<bool(const E &)> const &isTargetFunc) const
|
|
// {
|
|
// Node<E> *nextPtr = this->head;
|
|
// while (nextPtr != NULL) {
|
|
// if (isTargetFunc(nextPtr->getContent())) {
|
|
// return nextPtr->getContent();
|
|
// }
|
|
// nextPtr = nextPtr->getNextPtr();
|
|
// }
|
|
// throw(ValueError("Target not found!"));
|
|
// }
|
|
|
|
// template <class E>
|
|
// List<E> &List<E>::filter(std::function<bool(const E &)> const &isTargetFunc)
|
|
// {
|
|
// if (this->_length == 0) {
|
|
// return *this;
|
|
// }
|
|
// while (this->_length > 0 && !isTargetFunc(this->head->getContent())) {
|
|
// Node<E> *newHead = this->head->getNextPtr();
|
|
// delete this->head;
|
|
// this->head = newHead;
|
|
// this->_length--;
|
|
// }
|
|
// if (this->_length == 0) {
|
|
// return *this;
|
|
// }
|
|
// Node<E> *current = this->head;
|
|
// while (current->getNextPtr() != NULL) {
|
|
// if (!isTargetFunc(current->getNextPtr()->getContent())) {
|
|
// Node<E> *newNext = current->getNextPtr()->getNextPtr();
|
|
// delete current->getNextPtr();
|
|
// current->setNext(newNext);
|
|
// continue;
|
|
// }
|
|
// current = current->getNextPtr();
|
|
// }
|
|
// return *this;
|
|
// }
|
|
|
|
// template <class E>
|
|
// const List<E>
|
|
// List<E>::filtered(std::function<bool(const E &)> const &isTargetFunc) const {
|
|
// return List<E>(*this).filter(isTargetFunc);
|
|
// }
|
|
|
|
// template <class E>
|
|
// const List<E> List<E>::sorted(
|
|
// std::function<bool(const E &, const E &)> const &isCorrectOrderFunc)
|
|
// const { return List<E>(*this).sort(isCorrectOrderFunc);
|
|
// }
|
|
|
|
template <class E> Iterator<E> &&List<E>::iterate() {
|
|
return Iterator<E>(this->head);
|
|
}
|
|
|
|
template <class E> Iterator<E> &&List<E>::iterate(int index) {
|
|
// index = this->getIndexInRange(index);
|
|
if (index == 0) {
|
|
return Iterator<E>(this->head);
|
|
}
|
|
return Iterator<E>(&this->head->getByIndex(index));
|
|
}
|
|
|
|
template <class E> Node<E>::Node() : content(0), nextNode(NULL){};
|
|
|
|
template <class E>
|
|
Node<E>::Node(E _content, Node *_nextNode)
|
|
: content(_content), nextNode(_nextNode){};
|
|
|
|
template <class E> Node<E>::~Node(){};
|
|
|
|
template <class E> E &Node<E>::getContent() {
|
|
return this->content;
|
|
}
|
|
|
|
template <class E> Node<E> *Node<E>::getNextPtr() {
|
|
return this->nextNode;
|
|
}
|
|
|
|
template <class E> Node<E> *Node<E>::setNext(Node<E> *_nextNode) {
|
|
Node<E> *temp = this->nextNode;
|
|
this->nextNode = _nextNode;
|
|
return temp;
|
|
}
|
|
|
|
template <class E> Node<E> &Node<E>::getTail() {
|
|
if (this->nextNode == NULL) {
|
|
return *this;
|
|
}
|
|
return this->nextNode->getTail();
|
|
}
|
|
|
|
template <class E> Node<E> &Node<E>::getByIndex(const int index) {
|
|
if (index == 0) {
|
|
return *this;
|
|
}
|
|
return this->nextNode->getByIndex(index - 1);
|
|
}
|
|
|
|
template <class E> bool Node<E>::operator==(const E &other) {
|
|
return this->content == other;
|
|
}
|
|
|
|
template <class E> void Node<E>::destruct() {
|
|
if (this->nextNode != NULL) {
|
|
this->nextNode->destruct();
|
|
}
|
|
delete this;
|
|
}
|
|
|
|
template <class E> Iterator<E>::Iterator(Node<E> *start) : current(start){};
|
|
|
|
template <class E> bool Iterator<E>::hasNext() {
|
|
return this->current != NULL;
|
|
}
|
|
|
|
template <class E> Iterator<E>::operator bool() {
|
|
return this->hasNext();
|
|
}
|
|
|
|
template <class E> E &Iterator<E>::next() {
|
|
// if (!this->hasNext()) {
|
|
// throw(IndexError("Out of bound!"));
|
|
// }
|
|
E &temp = this->current->getContent();
|
|
this->current = this->current->getNextPtr();
|
|
return temp;
|
|
}
|
|
|
|
template <class E> E &Iterator<E>::peek() {
|
|
return this->current->getContent();
|
|
}
|
|
|
|
template <class E> Iterator<E> &Iterator<E>::insertHere(const E &_newItem) {
|
|
Node<E>* nextPtr = this->current->getNextPtr();
|
|
this->current->setNext(new Node<E>(_newItem, nextPtr));
|
|
return *this;
|
|
}
|
|
|
|
int main() {
|
|
List<int> aList(1);
|
|
int n;
|
|
int cmd, x, y;
|
|
scanf("%d", &n);
|
|
while (n > 0) {
|
|
scanf("%d", &cmd);
|
|
switch (cmd) {
|
|
case 1: {
|
|
scanf("%d %d", &x, &y);
|
|
if (x == 0) {
|
|
aList.insert(0, y);
|
|
break;
|
|
}
|
|
Iterator<int> iter = aList.iterate();
|
|
while (iter) {
|
|
if (iter.peek() == x) {
|
|
iter.insertHere(y);
|
|
break;
|
|
}
|
|
iter.next();
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
scanf("%d", &x);
|
|
Iterator<int> iter = aList.iterate();
|
|
while (iter) {
|
|
if (iter.next() == x) {
|
|
if (iter.hasNext()) {
|
|
printf("%d\n", iter.next());
|
|
}
|
|
else {
|
|
printf("0\n");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 3: {
|
|
scanf("%d", &x);
|
|
aList.remove(x);
|
|
break;
|
|
}
|
|
}
|
|
n--;
|
|
}
|
|
Iterator<int> iter = aList.iterate();
|
|
while(iter) {
|
|
printf("%d\n", iter.next());
|
|
}
|
|
return 0;
|
|
} |