下面的写法中,链表没有使用虚拟头结点,只有头指针,这样导致了插入删除要对第一个结点特殊对待,代码比较难看。如果加入了头结点,就可以一视同仁。
template<typename T>
struct Node {
T data;
Node<T> *next;
Node() = default;
Node(T d, Node<T> *n) : data(d), next(n) {}
};
template<typename T>
class LinkList {
private:
Node<T> *head;
size_t size;
public:
LinkList() : head(nullptr), size(0) {}
LinkList(Node<T> *h, size_t s) : head(h), size(s) {}
LinkList(const LinkList<T>& l);
LinkList<T>& operator=(const LinkList<T>& l);
virtual ~LinkList();
size_t getSize() const;
bool isEmpty() const;
void clear();
bool getElem(size_t i, T& e) const;
bool deleteElem(size_t i);
bool insertElem(size_t i, const T& e);
bool pushElem(const T& e);
};
template<typename T>
LinkList<T>::LinkList(const LinkList<T>& l) {
clear();
this->size = l.size;
Node<T> *q = l.head, *pre = nullptr;
while (q) {
if (!pre) {
head = new Node<T>(q->data, nullptr);
pre = head;
} else {
pre->next = new Node<T>(q->data, nullptr);
pre = pre->next;
}
q = q->next;
}
}
template<typename T>
LinkList<T>& LinkList<T>::operator=(const LinkList<T>& l) {
clear();
this->size = l.size;
Node<T> *q = l.head, *pre = nullptr;
while (q) {
if (!pre) {
head = new Node<T>(q->data, nullptr);
pre = head;
} else {
pre->next = new Node<T>(q->data, nullptr);
pre = pre->next;
}
q = q->next;
}
}
template<typename T>
LinkList<T>::~LinkList() {
clear();
}
template<typename T>
size_t LinkList<T>::getSize() const {
return this->size;
}
template<typename T>
bool LinkList<T>::isEmpty() const {
return this->size == 0;
}
template<typename T>
void LinkList<T>::clear() {
Node<T> *p = head;
while (p) {
Node<T> *t = p->next;
delete p;
p = t;
}
this->size = 0;
head = nullptr;
}
template<typename T>
bool LinkList<T>::getElem(size_t i, T& e) const {
if (i < 0 || i >= this->size) {
return false;
}
Node<T> *p = head;
for (int cnt = 0; cnt < i; ++cnt) {
p = p->next;
}
e = p->data;
return true;
}
template<typename T>
bool LinkList<T>::deleteElem(size_t i) {
if (i < 0 || i >= this->size) {
return false;
}
Node<T> *p = head;
--this->size;
if (i == 0) {
head = p->next;
delete p;
return true;
}
for (int cnt = 0; cnt < i - 1; ++i) {
p = p->next;
}
Node<T> *t = p->next;
p->next = p->next->next;
delete t;
return true;
}
template<typename T>
bool LinkList<T>::insertElem(size_t i, const T& e) {
if (i < 0 || i >= this->size) {
return false;
}
Node<T> *p = head;
Node<T> *newNode;
if (i == 0) {
newNode = new Node<T>(e, p->next);
head = newNode;
++this->size;
return true;
}
for (int cnt = 0; cnt < i - 1; ++cnt) {
p = p->next;
}
newNode = new Node<T>(e, p->next);
p->next = newNode;
++this->size;
return true;
}
template<typename T>
bool LinkList<T>::pushElem(const T& e) {
Node<T> *p = head;
++this->size;
if (!p) {
head = new Node<T>(e, nullptr);
return true;
}
if (!p->next) {
p->next = new Node<T>(e, nullptr);
return true;
}
while (p->next) {
p = p->next;
}
p->next = new Node<T>(e, nullptr);
return true;
}