由于类模板不支持分离编译,我们可以将模板类成员函数的声明和定义放在一个.hpp的文件中
SList.hpp
#pragma once #includeusing namespace std; #include template struct LinkNode //节点类(建议写法) { LinkNode(const T x); T _data; //节点的数据 LinkNode * _next; //指向该节点的下一个节点 }; template class SList { public: SList(); //构造函数 SList(const SList& s); //拷贝构造 SList &operator=(SList s); //赋值运算符的重载 ~SList(); //单链表的具体操作 void Reverse(); //翻转 void Swap(SList& s); void PrintSList(); //打印链表 void PushBack(const T& x); //在尾部插入一个节点 void Clear(); //链表置空 void PopBack(); //删除尾节点 void PushFront(T x); //头插 void PopFront(); //删除首节点 void Insert(LinkNode * pos, T x);//固定位置插入一个节点 void Erase(LinkNode * pos); //删除某一节点 LinkNode * Find(T x); //查找节点并返回这个节点的地址 int Amount(); //计算链表节点的数目 void Remove(T x); //查找某节点并删除 void RemoveAll(T x); //删除链表中所有的x private: LinkNode * _head; //指向头节点 LinkNode * _tail; //指向尾节点 }; template LinkNode ::LinkNode(const T x) :_data(x) , _next(NULL) {} template SList ::SList() //构造函数 : _head(NULL) , _tail(NULL) {} template SList ::SList(const SList & s) //拷贝构造 : _head(NULL) , _tail(NULL) { if (s._head == NULL) { return; } LinkNode * tmp = s._head; do{ PushBack(tmp->_data); tmp = tmp->_next; } while (tmp != s._head); } template SList & SList ::operator=(SList s) //赋值运算符的重载再优化(推荐写法) { if (this != &s) { swap(_head, s._head); swap(_tail, s._tail); } return *this; } template SList ::~SList() //析构 { Clear(); } template void SList ::Reverse() //链表逆置(利用头插新节点的方法) { if (_head == NULL || _head->_next == _tail) { return; } int ret = Amount(); _tail = new LinkNode (_head->_data); LinkNode * begin = NULL; LinkNode * tmp = _tail; while (--ret) { LinkNode * del = _head; _head = _head->_next; delete del; //这里不要忘记做清理工作,否则内存泄漏 begin = new LinkNode (_head->_data); begin->_next = tmp; _tail->_next = begin; tmp = begin; } _head = begin; } template void SList ::PrintSList()//打印链表 { //头结点为空时,无需打印链表 if (_head == NULL) { cout << "This SList is Empty !" << endl; return; } else { LinkNode * tmp = _head; do{ cout << tmp->_data << "-->"; tmp = tmp->_next; } while (tmp != _head); cout << endl; } } template void SList ::PushBack(const T& x) //在尾部插入一个节点 { //如果链表为空,插入节点后只有一个节点,此时_head=_tail if (_head == NULL) { _head = new LinkNode (x); _tail = _head; _tail->_next = _head; } else { _tail->_next = new LinkNode (x); _tail = _tail->_next; _tail->_next = _head; } } template void SList ::Clear() //链表置空 { LinkNode * begin = _head; while (begin != _tail) { _head = _head->_next; delete begin; begin = _head; } _head = NULL; _tail = NULL; } template void SList ::PopBack() //尾删 { if (_head == NULL) { cout << "This SList is empty !" << endl; } else if (_head == _tail) { delete _head; _head = NULL; _tail = NULL; } else { LinkNode * cur = _head; while (cur->_next != _tail) { cur = cur->_next; } delete _tail; _tail = cur; _tail->_next = _head; } } template void SList ::PushFront(T x) //头插 { if (_head == NULL) { PushBack(x); } else { LinkNode * tmp = _head; _head = new LinkNode (x); _head->_next = tmp; _tail->_next = _head; } } template void SList ::PopFront() //删除首节点 { if (_head == NULL) { cout << "This SList is empty !" << endl; return; } LinkNode * tmp = _head; _head = _head->_next; _tail->_next = _head; delete tmp; } //固定位置插入一个节点(这个函数需和Find函数搭配使用) //先用Find函数找到新节点需要插入的位置 //(将Find函数的返回值传给Insert函数的参数pos),再在pos节点后面插入新节点x template void SList ::Insert(LinkNode * pos, T x) { assert(pos); if (pos == _tail) { PushBack(x); } else { LinkNode * tmp = new LinkNode (x); tmp->_next = pos->_next; pos->_next = tmp; } } //删除某一节点,同样,要先找到该节点并传参给Erase函数 template void SList ::Erase(LinkNode * pos) { assert(pos); if (pos == _tail) { PopBack(); } if (pos == _head) { PopFront(); } else { LinkNode * prev = _head; while (prev->_next != pos) { prev = prev->_next; } prev->_next = pos->_next; delete pos; } } template LinkNode * SList ::Find(T x) //查找节点并返回这个节点的地址 { if (_head == NULL) { cout << "This SList is empty !" << endl; return NULL; } else { LinkNode * tmp = _head; do{ if (tmp->_data == x) { return tmp; } tmp = tmp->_next; } while (tmp != _head); return NULL; } } template int SList ::Amount() //计算链表节点的数目 { if (_head == NULL) { return 0; } else { int count = 0; LinkNode * cur = _head; while (cur != _tail) { count++; cur = cur->_next; } return ++count; } } template void SList ::Remove(T x) //查找某节点并删除 { if (_head == NULL) { cout << "This SList is empty !" << endl; } else { LinkNode* tmp = Find(x); if (tmp != NULL) { Erase(tmp); } } } template void SList ::RemoveAll(T x) //删除链表中所有的x { if (_head == NULL) { cout << "This SList is empty !" << endl; return; } //如果链表不为空,设置left和right前后指针,从头至尾遍历一遍,delete节点的data为x的节点 LinkNode * left = _tail; LinkNode * right = _head; int count = Amount(); while (count--) { //当要删掉的节点是头节点时,需要注意头节点要指向它的下一个节点 //当要删掉的节点是尾节点时,需要注意尾节点要指向它的上一个节点 //当left和right指向同一块要删掉的节点时,将链表置空 if (right->_data == x) { if (_head == right) { _head = _head->_next; } if (_tail == right) { _tail = left; } if (right == left) { _head = NULL; _tail = NULL; return; } LinkNode * tmp = right; right = right->_next; delete tmp; left->_next = right; } else { left = right; right = right->_next; } } }
Test.cpp
// 用例测试 #include"Slist.hpp" void Test() { SListlist1; list1.PushBack(1); list1.PushBack(2); list1.PushBack(3); list1.PushBack(4); list1.PushBack(5); cout << "SList 1: "; list1.PrintSList(); SList list2 = list1; cout << "SList 2: "; list2.PrintSList(); SList list3 (list1); cout << "SList 3: "; list3.PrintSList(); SList list4; list4 = list1; cout << "SList 4: "; list4.PrintSList(); cout << endl; list1.RemoveAll(2); cout << "SList 1: "; list1.PrintSList(); list2.Reverse(); cout << "SList 2: "; list2.PrintSList(); list3.PopBack(); cout << "SList 3: "; list3.PrintSList(); list4.Clear(); cout << "SList 4: "; list4.PrintSList(); cout << endl; list1.Erase(list1.Find(4)); cout << "SList 1: "; list1.PrintSList(); list1.PopFront(); cout << "SList 1: "; list1.PrintSList(); list1.PushFront(0); cout << "SList 1: "; list1.PrintSList(); list1.Insert(list1.Find(3), 0); cout << "SList 1: "; list1.PrintSList(); list1.RemoveAll(0); cout << "SList 1: "; list1.PrintSList(); } int main() { Test(); system("pause"); }