单链表
template <typename T>
class LinkedList {
typedef LinkedList self;
typedef T value_type;
class Node {
friend LinkedList;
public:
template <typename R>
constexpr Node(const R &value, Node *next) : value_(value), next_(next) {}
constexpr Node(const value_type &value, Node *next) : value_(value), next_(next) {}
constexpr Node(const value_type &value) : Node(value, nullptr) {}
constexpr Node() : value_(), next_(nullptr) {}
~Node() { next_ = nullptr; }
private:
value_type value_;
Node *next_;
}; // class Node
public:
LinkedList() : head_(nullptr), tail_(nullptr), size_(0) {}
~LinkedList() {
while (head_) {
Node *next = head_->next_;
delete head_;
head_ = next;
}
tail_ = nullptr;
}
size_t size() const { return size_; }
value_type &at(size_t index) {
return const_cast<value_type&>(const_cast<const self*>(this)->at(index));
}
const value_type &at(size_t index) const {
if (index < 0 || index >= size_) throw std::out_of_range(
std::string("LinkedList.at(") +
std::to_string(index) +
") failed as the size is " +
std::to_string(size_)
);
Node *node = head_;
while (index--) node = node->next_;
return node->value_;
}
void add_at_head(const value_type &val) {
++size_;
if (head_) head_ = new Node(val, head_);
else head_ = tail_ = new Node(val);
}
void add_at_tail(const value_type &val) {
++size_;
if (tail_) tail_ = tail_->next_ = new Node(val);
else head_ = tail_ = new Node(val);
}
void add_by_index(size_t index, const value_type &val) {
if (index > size_) return;
if (index <= 0) {
add_at_head(val);
return;
}
if (index == size_) {
add_at_tail(val);
return;
}
++size_;
Node *node = head_;
while (--index) node = node->next_;
node->next_ = new Node(val, node->next_);
}
void delete_by_index(size_t index) {
if (index < 0 || index >= size_) return;
--size_;
if (size_ == 0) {
delete head_;
head_ = tail_ = nullptr;
return;
}
Node *del = head_;
if (index == 0) head_ = head_->next_;
else {
Node *node = head_;
while (--index) node = node->next_;
del = node->next_;
if (del == tail_) tail_ = node;
node->next_ = del->next_;
}
delete del;
}
private:
Node *head_, *tail_;
size_t size_;
};
单循环链表
template <typename T>
class CircularlyLinkedList {
typedef CircularlyLinkedList self;
typedef T value_type;
class Node {
friend CircularlyLinkedList;
public:
template <typename R>
constexpr Node(const R &value, Node *next) : value_(value), next_(next) {}
constexpr Node(const value_type &value, Node *next) : value_(value), next_(next) {}
constexpr Node(const value_type &value) : Node(value, nullptr) {}
constexpr Node() : value_(), next_(nullptr) {}
~Node() { next_ = nullptr; }
private:
const value_type & value_;
Node *next_;
}; // class Node
public:
CircularlyLinkedList() : tail_(nullptr), size_(0) {}
~CircularlyLinkedList() {
if (tail_) {
Node *node = tail_->next_;
while (node != tail_) {
Node *next = node->next_;
delete node;
node = next;
}
delete tail_;
tail_ = nullptr;
}
}
size_t size() const { return size_; }
value_type &at(size_t index) {
return const_cast<value_type&>(const_cast<const self*>(this)->at(index));
}
const value_type &at(size_t index) const {
if (index < 0 || index >= size_) throw std::out_of_range(
std::string("CircularlyLinkedList.at(") +
std::to_string(index) +
") failed as the size is " +
std::to_string(size_)
);
Node *node = tail_->next_;
while (index--) node = node->next_;
return node->value_;
}
void add_head(const value_type &val) {
++size_;
if (tail_) tail_->next_ = new Node(val, tail_->next_);
else init_head(val);
}
void add_tail(const value_type &val) {
++size_;
if (tail_) tail_ = tail_->next_ = new Node(val, tail_->next_);
else init_head(val);
}
void add_by_index(size_t index, const value_type &val) {
if (index > size_) return;
if (index <= 0) {
add_head(val);
return;
}
if (index == size_) {
add_tail(val);
return;
}
++size_;
Node *node = tail_;
while (index--) node = node->next_;
node->next_ = new Node(val, node->next_);
}
void delete_by_index(size_t index) {
if (index < 0 || index >= size_) return;
--size_;
if (size_ == 0) {
delete_head();
return;
}
Node *node = tail_;
while (index--) node = node->next_;
Node *del = node->next_;
if (del == tail_) tail_ = node;
node->next_ = del->next_;
delete del;
}
private:
void init_head(const value_type &val) {
tail_ = new Node(val);
tail_->next_ = tail_;
}
void delete_head() {
delete tail_;
tail_ = nullptr;
}
Node *tail_; // tail_->next_ is head_
size_t size_;
}; // class CircularlyLinkedList
双循环链表
template <typename T>
class CircularlyDoubleLinkedList {
typedef CircularlyDoubleLinkedList self;
typedef T value_type;
class Node {
friend CircularlyDoubleLinkedList;
public:
template <typename R>
constexpr Node(const R &value, Node *prev, Node *next)
: value_(value), prev_(prev), next_(next) {}
constexpr Node(const value_type &value, Node *prev, Node *next)
: value_(value), prev_(prev), next_(next) {}
constexpr Node(const value_type &value) : Node(value, nullptr, nullptr) {}
constexpr Node() : value_(), prev_(nullptr), next_(nullptr) {}
~Node() { prev_ = next_ = nullptr; }
private:
value_type value_;
Node *prev_, *next_;
}; // class Node
public:
CircularlyDoubleLinkedList()
: entry_(new Node), size_(0){ entry_->prev_ = entry_->next_ = entry_; }
~CircularlyDoubleLinkedList() {
Node *node = entry_;
do {
Node *next = node->next_;
delete node;
node = next;
} while (node != entry_);
entry_ = nullptr;
}
size_t size() const { return size_; }
value_type &at(size_t index) {
return const_cast<value_type&>(const_cast<const self*>(this)->at(index));
}
const value_type &at(size_t index) const {
if (index < 0 || index >= size_) throw std::out_of_range(
std::string("CircularlyDoubleLinkedList.at(") +
std::to_string(index) +
") failed as the size is " +
std::to_string(size_)
);
return get_node(index)->value_;
}
void add_at_head(const value_type &val) {
++size_;
entry_->next_ = entry_->next_->prev_ = new Node(val, entry_, entry_->next_);
}
void add_at_tail(const value_type &val) {
++size_;
entry_->prev_ = entry_->prev_->next_ = new Node(val, entry_->prev_, entry_);
}
void add_by_index(size_t index, const value_type &val) {
if (index > size_) return;
if (index <= 0) {
add_at_head(val);
return;
}
if (index == size_) {
add_at_tail(val);
return;
}
Node *node = get_node(index);
node->prev_ = node->prev_->next_ = new Node(val, node->prev_, node);
++size_;
}
void delete_by_index(size_t index) {
if (index < 0 || index >= size_) return;
Node *del = get_node(index);
--size_;
del->prev_->next_ = del->next_;
del->next_->prev_ = del->prev_;
delete del;
}
private:
Node *get_node(size_t index) const {
Node *node = entry_;
if (index > size_ >> 1) {
index = size_ - index - 1;
do node = node->prev_; while (index--);
} else {
do node = node->next_; while (index--);
}
return node;
}
Node *entry_;
size_t size_;
};