C++数据结构 之 链表_Linked List
源代码只包含头文件
注:需要C++11的支持
一、链表
链表的思想类似于一根链子,环环相扣,每一个链环都是一个节点,每个节点中有自己的数据,还有指向前一个节点和后一个节点的指针。因此访问链表,不能随机访问,必须一个接一个,显然访问时间较长,但也是线性时间以内。
链表有头有尾,在本实现中,即使是空链表,头尾节点也是存在的。
支持的操作:
1、push_back (尾压入):将节点从尾部压入链表中。
2、push_front (首压入):将节点从首部压入链表中。
3、back 返回尾节点前一个节点的数据。
4、front 返回首节点下一个节点的数据。
5、front_insert 在当前节点的前一个位置一个新的节点。
6、back_front 在当先节点的下一个位置插入一个新的节点。
7、erase 删除当前节点,或者删除制定范围内的节点(此范围 [begin,end),注意括号的区别)。
8、clear 删除所有,初头尾节点以外的节点。
9、resize 添加n个默认初始化数据的节点
10、sort 按照数据less函数对象给链表排序。
11、search 返回所要查找数据的迭代器。
12、begin 返回首节点的下一个节点的迭代器。
13、end 返回尾节点的迭代器。
14 、rbegin 返回为节点的上一个节点的迭代器。
15、rend 返回首节点的迭代器。
示意图:
二、源代码:
#ifndef LIST_H
#define LIST_H
#include <memory>
#include <stdexcept>
#include <vector>
#include <algorithm>
using std::shared_ptr;
using std::make_shared;
template<typename Data>
class List {
friend class const_iterator;
private:
struct Node {
Node() = default;
Data data;
shared_ptr<Node> prev = nullptr;
shared_ptr<Node> next = nullptr;
};
shared_ptr<Node> head = make_shared<Node>();
shared_ptr<Node> tail = make_shared<Node>();
void initialize() {
head->next = tail;
tail->prev = head;
}
size_t List_Size = 0;
public:
// CLASS const_iterator
class const_iterator {
friend class List<Data>;
public:
const_iterator() = default;
~const_iterator() = default;
const_iterator(shared_ptr<Node> p) : ptr(p) {}
const Data& operator*() const {
return ptr->data;
}
const_iterator& operator+(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->next != nullptr) {
ptr = ptr->next;
}
}
return *this;
}
const_iterator& operator-(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->prev != nullptr) {
ptr = ptr->prev;
}
}
return *this;
}
const_iterator& operator++() {
ptr = ptr->next;
return *this;
}
const_iterator& operator++(int) {
const_iterator temp = *this;
++*this;
return temp;
}
const_iterator& operator--() {
ptr = ptr->prev;
return *this;
}
const_iterator& operator--(int) {
const_iterator temp = *this;
--*this;
return temp;
}
bool operator==(const const_iterator &rhs) const {
return ptr == rhs.ptr;
}
bool operator!=(const const_iterator &rhs) const {
return !(*this == rhs);
}
protected:
shared_ptr<Node> ptr;
};
// CLASS iterator
class iterator : public const_iterator {
friend class List<Data>;
public:
iterator() = default;
~iterator() = default;
Data& operator*() {
return ptr->data;
}
const Data& operator*() const {
return const_iterator::operator*();
}
iterator& operator+(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->next != nullptr) {
ptr = ptr->next;
}
}
return *this;
}
iterator& operator-(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->prev != nullptr) {
ptr = ptr->prev;
}
}
return *this;
}
iterator& operator++() {
ptr = ptr->next;
return *this;
}
iterator& operator++(int) {
iterator temp = *this;
++*this;
return temp;
}
iterator& operator--() {
ptr = ptr->prev;
return *this;
}
iterator& operator--(int) {
iterator temp = *this;
--*this;
return temp;
}
protected:
iterator(shared_ptr<Node> p) : const_iterator(p) {}
};
// CLASS const_reverse_iterator
class const_reverse_iterator {
friend class List<Data>;
public:
const_reverse_iterator() = default;
~const_reverse_iterator() = default;
const_reverse_iterator(shared_ptr<Node> p) : ptr(p) {}
const Data& operator*() const {
return ptr->data;
}
const_reverse_iterator& operator+(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->prev != nullptr) {
ptr = ptr->prev;
}
}
return *this;
}
const_reverse_iterator& operator-(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->next != nullptr) {
ptr = ptr->next;
}
}
return *this;
}
const_reverse_iterator& operator++() {
ptr = ptr->prev;
return *this;
}
const_reverse_iterator& operator++(int) {
const_reverse_iterator temp = *this;
++*this;
return temp;
}
const_reverse_iterator& operator--() {
ptr = ptr->next;
return *this;
}
const_reverse_iterator& operator--(int) {
const_reverse_iterator temp = *this;
--*this;
return temp;
}
bool operator==(const const_reverse_iterator& rhs) {
return ptr == rhs.ptr;
}
bool operator!=(const const_reverse_iterator& rhs) {
return !(*this == rhs);
}
protected:
shared_ptr<Node> ptr;
};
// CLASS reverse_iterator
class reverse_iterator : public const_reverse_iterator {
friend class List<Data>;
public:
reverse_iterator() = default;
~reverse_iterator() = default;
Data& operator*() {
return ptr->data;
}
const Data& operator*() const {
return const_reverse_iterator::operator*();
}
reverse_iterator& operator+(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->prev != nullptr) {
ptr = ptr->prev;
}
}
return *this;
}
reverse_iterator& operator-(long long LL) {
for (auto i = 0; i != LL; ++i) {
if (ptr->next != nullptr) {
ptr = ptr->next;
}
}
return *this;
}
reverse_iterator& operator++() {
ptr = ptr->prev;
return *this;
}
reverse_iterator& operator++(int) {
reverse_iterator temp = *this;
++*this;
return temp;
}
reverse_iterator& operator--() {
ptr = ptr->next;
return *this;
}
reverse_iterator& operator--(int) {
reverse_iterator temp = *this;
--*this;
return temp;
}
protected:
reverse_iterator(shared_ptr<Node> p) : const_reverse_iterator(p) {}
};
public:
List() { initialize(); }
~List() = default;
//List(const List &rhs) {
// clear();
// for (auto &i : rhs) {
// push_back(i);
// }
//}
//List& operator=(const List &rhs) {
// if (this == &rhs) {
// return *this;
// }
// clear();
// for (auto &i : rhs) {
// push_back(i);
// }
// return *this;
//}
iterator begin() {
return iterator(head->next);
}
const_iterator begin() const {
return const_iterator(head->next);
}
reverse_iterator rbegin() {
return reverse_iterator(tail->prev);
}
const_reverse_iterator rbegin() const {
return const_reverse_iterator(tail->prev);
}
iterator end() {
return iterator(tail);
}
const_iterator end() const {
return const_iterator(tail);
}
reverse_iterator rend() {
return reverse_iterator(head);
}
const_reverse_iterator rend() const {
return const_reverse_iterator(head);
}
// Front insert.
iterator front_insert(iterator itr, const Data& data) {
shared_ptr<Node> p = itr.ptr;
++List_Size;
auto a = make_shared<Node>();
a->data = data;
a->prev = p->prev;
a->next = p;
p->prev = a;
a->prev->next = a;
return iterator(a);
//return iterator(p->prev = p->prev->next = make_shared<Node>(data, p->prev, p));
}
iterator front_insert(iterator itr) {
shared_ptr<Node> p = itr.ptr;
++List_Size;
auto a = make_shared<Node>();
a->prev = p->prev;
a->next = p;
p->prev = a;
a->prev->next = a;
return iterator(a);
}
// Back_insert.
iterator back_insert(iterator itr, const Data& data) {
shared_ptr<Node> p = itr.ptr;
++List_Size;
auto a = make_shared<Node>();
a->data = data;
a->prev = p;
a->next = p->next;
p->next = a;
a->next->prev = a;
return iterator(a);
//return iterator(p->next = p->next->prev = make_shared<Node>(data, p, p->next));
}
iterator back_insert(iterator itr) {
shared_ptr<Node> p = itr.ptr;
++List_Size;
auto a = make_shared<Node>();
a->prev = p;
a->next = p->next;
p->next = a;
a->next->prev = a;
return iterator(a);
}
iterator erase(iterator itr) {
shared_ptr<Node> p = itr.ptr;
iterator itaval(p->next);
try {
if (p == head) {
throw runtime_error("No elements can erase!");
}
else if (p == tail) {
throw runtime_error("No elements can erase!");
}
else {
p->prev->next = p->next;
p->next->prev = p->prev;
--List_Size;
}
}
catch (runtime_error err) {
cout << err.what() << endl;
}
return itaval;
}
iterator erase(iterator begin, iterator end) { // [begin, end)
while (begin != end) {
begin = erase(begin);
}
return iterator(end);
}
void clear() {
while (!empty()) {
pop_front();
}
}
void print() {
for (auto &i : *this) {
cout << i << endl;
}
}
void resize(long long LL) {
for (auto i = 0; i != LL; ++i) {
push_back();
}
}
void resize(long long LL, const Data &x) {
for (auto i = 0; i != LL; ++i) {
push_back(x);
}
}
void sort() {
std::vector<Data> temp_v;
for (auto &i : *this) {
temp_v.push_back(i);
}
std::stable_sort(temp_v.begin(), temp_v.end());
clear();
for (auto &i : temp_v) {
push_back(i);
}
}
iterator search(const Data &x) {
auto temp_count = 0;
for (auto &i : *this) {
if (i != x) {
++temp_count;
}
else {
break;
}
}
return begin() + temp_count;
}
bool empty() { return List_Size == 0; }
size_t size() { return List_Size; }
Data& front() { return *begin(); }
const Data& front() const { return front(); }
Data& back() { return *--end(); }
const Data& back() const { return back(); }
void push_front() { front_insert(begin()); }
void push_front(const Data &x) { front_insert(begin(), x); }
void push_back() { back_insert(--end()); }
void push_back(const Data &x) { back_insert(--end(), x); }
void pop_front() { erase(begin()); }
void pop_back() { erase(--end()); }
};
#endif // !LIST_H
注释:所有对节点的访问,已经抽象成为使用迭代器访问。