定义
- 链表的节点
template <class T>
class Node {
public:
T val;
Node* next;
Node() = default;
Node(const T& t, Node* nxt = nullptr) : val(t), next(nxt) {}
};
- 链表
template <class T>
class LinkedList {
private:
Node<T>* __head;
Node<T>* __tail;
unsigned __size;
public:
LinkedList() : __head(nullptr), __tail(nullptr), __size(0) {}
LinkedList(T* a, int n);
void insertHead(const T& t);
void insertTail(const T& t);
void insert(unsigned i, const T& t);
T removeHead();
T removeTail();
bool remove(const T& t);
bool empty() { return __size == 0 ? true : false; }
unsigned size() { return __size; }
void reverse();
void reverse(unsigned i);
void reverse(unsigned i, unsigned j);
int indexOf(T t);
T at(int index);
~LinkedList();
template <class U>
friend std::ostream& operator<<(std::ostream& os, const LinkedList<U>& l);
};
实现
template <class T>
LinkedList<T>::LinkedList(T* a, int n) {
LinkedList();
for (; --n != -1;)
insertTail(a[n]);
}
template <class T>
void LinkedList<T>::insertHead(const T& t) {
Node<T>* node = new Node<T>(t);
if (__head == nullptr) {
__head = node;
__tail = __head;
}
else {
node->next = __head;
__head = node;
}
++__size;
}
template <class T>
void LinkedList<T>::insertTail(const T& t) {
Node<T>* node = new Node<T>(t);
if (__tail == nullptr) {
__tail = node;
__head = __tail;
}
else {
__tail->next = node;
__tail = __tail->next;
}
++__size;
}
template <class T>
void LinkedList<T>::insert(unsigned i, const T& t) {
Node<T>* node = new Node<T>(t);
if (__head == nullptr || i > __size) {
insertTail(t);
return;
}
if (i == 0) {
insertHead(t);
return;
}
Node<T>*pre = nullptr, *p = __head;
while (--i) {
pre = p;
p = p->next;
}
node->next = p;
pre->next = node;
++__size;
}
template <class T>
T LinkedList<T>::removeHead() {
if (__size == 0)
throw "Exception : Remove form an empty List :(";
--__size;
Node<T>* p = __head;
T ret = std::move(p->val);
__head = __head->next;
delete p;
return ret;
}
template <class T>
T LinkedList<T>::removeTail() {
if (__size == 0)
throw "Exception : Remove form an empty List :(";
--__size;
Node<T>* p = __head;
for (Node<T>* i = __head; i->next != nullptr; i = i->next)
p = i;
if (p == __head) {
T t = __head->val;
delete __head;
__head = nullptr;
__tail = nullptr;
return t;
}
Node<T>* node = p->next;
T ret = std::move(node->val);
p->next = nullptr;
__tail = p;
delete node;
return ret;
}
template <class T>
bool LinkedList<T>::remove(const T& t) {
if (__size == 0)
throw "Exception : Remove form an empty List :(";
Node<T>* p = __head;
Node<T>* i = __head;
for (; i != nullptr && i->val != t; i = i->next) {
p = i;
}
if (i == nullptr) {
return false;
}
if (p == __head) {
removeHead();
return true;
}
Node<T>* node = p->next;
p->next = node->next;
delete node;
--__size;
return true;
}
template <class T>
void LinkedList<T>::reverse() {
__tail = __head;
for (Node<T>*p = __head->next, *pre = __head; p; pre->next = p) {
Node<T>* node = p;
p = p->next;
node->next = __head;
__head = node;
}
}
template <class T>
void LinkedList<T>::reverse(unsigned i) {
if (i < 0 || i >= __size)
throw "Exception : Index out of range !";
if (i == __size) {
reverse();
return;
}
Node<T>*tail = __head, *head = __head;
for (int k = 0; k < i; ++k) {
tail = tail->next;
}
for (Node<T>*p = __head->next, *pre = __head; p != tail; pre->next = p) {
Node<T>* node = p;
p = p->next;
node->next = __head;
__head = node;
}
head->next = tail;
}
template <class T>
void LinkedList<T>::reverse(unsigned i, unsigned j) {
if (i < 0 || i > j || j >= __size)
throw "Exception : Index out of range !";
if (i == j)
return;
if (i == 0) {
reverse(j);
return;
}
Node<T>*pre = __head, *s, *p = pre->next, *next = nullptr;
int k = 1;
for (; k < i; ++k) {
pre = p;
p = p->next;
}
for (; k < j; ++k)
p = p->next;
next = p->next;
p = pre->next;
k = j - i + 1;
for (; k--;) {
Node<T>* node = p;
p = p->next;
node->next = next;
next = node;
}
pre->next = next;
}
template <class T>
int LinkedList<T>::indexOf(T t) {
if (__head == nullptr)
throw "Exception : Empty List :(";
int index = 0;
for (Node<T>* p = __head; p != nullptr; p = p->next) {
if (p->val == t)
return index;
++index;
}
return -1;
}
template <class T>
T LinkedList<T>::at(int i) {
if (i < 0 || i >= __size)
throw "Exception : Index out of range !";
Node<T>* p = __head;
for (; i--;)
p = p->next;
return p->val;
}
template <class T>
LinkedList<T>::~LinkedList() {
while (__head != nullptr) {
Node<T> p = __head;
__head = __head->next;
delete p;
}
__tail = nullptr;
}
template <class U>
std::ostream& operator<<(std::ostream& os, const LinkedList<U>& l) {
if (l.__head != nullptr)
for (Node<U>* i = l.__head; i != nullptr; i = i->next) {
os << i->val << " ";
}
else
os << "null ";
return os;
}
测试
#include "LinkedList.h"
using namespace std;
LinkedList<string>* ll;
void init() {
cout << "----\n初始化\n";
ll = new LinkedList<string>();
ll->insertHead("Quanwei");
ll->insertHead("Tang");
ll->insertHead("Hi");
ll->insertTail("Hello");
ll->insertTail("Linked");
ll->insertTail("List");
ll->insertTail("Node");
cout << "init: " << *ll << "\n";
}
void testInsert() {
cout << "----\n插入测试:\n";
ll->insert(0, "芜湖~");
cout << "insert: \n"
<< *ll << "\n";
ll->insert(0, "芜湖~");
cout << "insert: \n"
<< *ll << "\n";
ll->insert(ll->size(), "尾巴前面一个~");
cout << "insert: \n"
<< *ll << "\n";
ll->insert(ll->size() + 1, "尾巴后面一个~");
cout << "insert: \n"
<< *ll << "\n";
ll->insert(100, "ll->insert(100, \"\");");
cout << "insert: \n"
<< *ll << "\n";
ll->insert(-100, "ll->insert(-100, \"\");");
cout << "insert: \n"
<< *ll << "\n";
}
void testIndexOf() {
cout << "----\n测试获取元素下标: \n";
cout << "ll->indexOf(\"ll->insert(-100, \"\");\")\t" << ll->indexOf("ll->insert(-100, \"\");") << '\n';
cout << "ll->indexOf(\"芜湖~\")\t" << ll->indexOf("芜湖~") << '\n';
}
void testAt() {
cout << "----\n测试通过下标获取: \n";
cout << "at(0): " << ll->at(0) << '\n';
cout << "at(size-1): " << ll->at(ll->size() - 1) << '\n';
}
void testReverse() {
cout << "----\n测试数组反转: \n";
ll->reverse();
cout << "全部反转后: \n"
<< *ll << '\n';
ll->reverse(5);
cout << "反转 [0, 5] 后: \n"
<< *ll << '\n';
ll->reverse(2, ll->size() - 2);
cout << "反转 [2, ll->size()-2] 后: \n"
<< *ll << '\n';
}
void testRemove() {
cout << "----\n测试移除元素: \n";
cout << "removeHead: " << ll->removeHead() << '\n';
cout << "removeTail: " << ll->removeTail() << '\n';
cout << "remove(\" Tang \"): " << (ll->remove("Tang") ? "true" : "false") << '\n';
cout << "remove(\" Tang \"): " << (ll->remove("Tang") ? "true" : "false") << '\n';
cout << "移除后: " << *ll << '\n';
}
void testException() {
try {
cout << "at(-1): ";
cout << ll->at(-1) << '\n';
}
catch (const char* e) {
std::cerr << e << '\n';
}
}
int main(int argc, char const* argv[]) {
init();
testInsert();
testIndexOf();
testAt();
testReverse();
testRemove();
testException();
return 0;
}