更改文件夹名。
This commit is contained in:
866
大作业/ListE.hpp → FinalProject/ListE.hpp
Executable file → Normal file
866
大作业/ListE.hpp → FinalProject/ListE.hpp
Executable file → Normal file
@@ -1,434 +1,434 @@
|
||||
#pragma once
|
||||
#include "Exceptions.hpp"
|
||||
#include "Node.hpp"
|
||||
#include <functional>
|
||||
|
||||
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 &isCorrentOrderFunc);
|
||||
|
||||
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> int List<E>::getIndexInRange(int index) const {
|
||||
if (index < 0) {
|
||||
index += this->_length;
|
||||
}
|
||||
if (index < 0 || index >= _length) {
|
||||
throw(IndexError("Index not in range!"));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void List<E>::quickSort(
|
||||
int leftBound, int rightBound,
|
||||
std::function<bool(const E &, const E &)> const &isCorrentOrderFunc) {
|
||||
if (leftBound >= rightBound) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pivot = leftBound;
|
||||
int left = leftBound;
|
||||
int right = rightBound;
|
||||
|
||||
while (left < right) {
|
||||
while (isCorrentOrderFunc((*this)[pivot], (*this)[right]) &&
|
||||
right > left) {
|
||||
right--;
|
||||
}
|
||||
this->swap(pivot, right);
|
||||
pivot = right;
|
||||
|
||||
while (isCorrentOrderFunc((*this)[left], (*this)[pivot]) &&
|
||||
right > left) {
|
||||
left++;
|
||||
}
|
||||
this->swap(left, pivot);
|
||||
pivot = left;
|
||||
}
|
||||
|
||||
quickSort(leftBound, pivot - 1, isCorrentOrderFunc);
|
||||
quickSort(pivot + 1, rightBound, isCorrentOrderFunc);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
template <class E> const E &List<E>::operator[](const int index) const {
|
||||
return this->head->getByIndex(getIndexInRange(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!"));
|
||||
}
|
||||
|
||||
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 std::move(Iterator<E>(this->head));
|
||||
}
|
||||
|
||||
template <class E> Iterator<E> &&List<E>::iterate(int index) {
|
||||
index = this->getIndexInRange(index);
|
||||
if (index == 0) {
|
||||
return std::move(Iterator<E>(this->head));
|
||||
}
|
||||
return std::move(Iterator<E>(&this->head->getByIndex(index)));
|
||||
#pragma once
|
||||
#include "Exceptions.hpp"
|
||||
#include "Node.hpp"
|
||||
#include <functional>
|
||||
|
||||
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 &isCorrentOrderFunc);
|
||||
|
||||
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> int List<E>::getIndexInRange(int index) const {
|
||||
if (index < 0) {
|
||||
index += this->_length;
|
||||
}
|
||||
if (index < 0 || index >= _length) {
|
||||
throw(IndexError("Index not in range!"));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void List<E>::quickSort(
|
||||
int leftBound, int rightBound,
|
||||
std::function<bool(const E &, const E &)> const &isCorrentOrderFunc) {
|
||||
if (leftBound >= rightBound) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pivot = leftBound;
|
||||
int left = leftBound;
|
||||
int right = rightBound;
|
||||
|
||||
while (left < right) {
|
||||
while (isCorrentOrderFunc((*this)[pivot], (*this)[right]) &&
|
||||
right > left) {
|
||||
right--;
|
||||
}
|
||||
this->swap(pivot, right);
|
||||
pivot = right;
|
||||
|
||||
while (isCorrentOrderFunc((*this)[left], (*this)[pivot]) &&
|
||||
right > left) {
|
||||
left++;
|
||||
}
|
||||
this->swap(left, pivot);
|
||||
pivot = left;
|
||||
}
|
||||
|
||||
quickSort(leftBound, pivot - 1, isCorrentOrderFunc);
|
||||
quickSort(pivot + 1, rightBound, isCorrentOrderFunc);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
template <class E> const E &List<E>::operator[](const int index) const {
|
||||
return this->head->getByIndex(getIndexInRange(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!"));
|
||||
}
|
||||
|
||||
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 std::move(Iterator<E>(this->head));
|
||||
}
|
||||
|
||||
template <class E> Iterator<E> &&List<E>::iterate(int index) {
|
||||
index = this->getIndexInRange(index);
|
||||
if (index == 0) {
|
||||
return std::move(Iterator<E>(this->head));
|
||||
}
|
||||
return std::move(Iterator<E>(&this->head->getByIndex(index)));
|
||||
}
|
||||
210
大作业/Node.hpp → FinalProject/Node.hpp
Executable file → Normal file
210
大作业/Node.hpp → FinalProject/Node.hpp
Executable file → Normal file
@@ -1,106 +1,106 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
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;
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user