上一篇博客介绍了模板类顺序表,此篇博客主要是模板类链表的实现。
#pragma once
#include<iostream>
#include<string>
using namespace std;
template<typename T>
struct Node
{
public:
Node(const T&x)
:_data(x), _next(NULL), _prev(NULL)
{}
T _data;
Node<T>*_next;
Node<T>*_prev;
};
template<typename T>
class LinkList
{
template<typename T>
friend ostream&operator<<(ostream&os, const LinkList<T>&list);
public:
LinkList()
:_head(NULL), _tail(NULL), _sz(0)
{}
~LinkList()
{
Release();
}
LinkList(const LinkList<T>&list); //拷贝构造
void PushBack(T x); //尾插
void PopBack(); //尾删
void PushFront(T x); //头插
void PopFront(); //头删
Node<T>* Find(T x); //查找指定元素的地址
void Insert(Node<T>* node, T x); //指定位置插入指定数据
void Remove(T x); //删除指定元素
void RemoveAll(T x); //删除链表里出现的所有指定数据
void Erase(Node<T>* node); //指定位置删除
void BubbleSort(); //冒泡排序
int& GetSz()
{
return _sz;
}
public:
void Release()
{
Node<T>* cur = _head;
while (cur)
{
Node<T>*tmp = cur;
cur = cur->_next;
delete tmp;
tmp = NULL;
}
_head = NULL;
_tail = NULL;
_sz = 0;
}
Node<T>*_head;
Node<T>*_tail;
int _sz;
};
template<typename T>
ostream&operator<<(ostream&os, const LinkList<T>&list)
{
Node<T>*cur = list._head;
while (cur)
{
os << cur->_data << "-";
cur = cur->_next;
}
cout << "end" << endl;
return os;
}
template<typename T>
LinkList<T>::LinkList(const LinkList<T>&list)
{
Node<T>* cur = list._head;
while (cur)
{
PushBack(cur->_data);
_sz++;
cur = cur->_next;
}
}
template<typename T>
void LinkList<T>::PushBack(T x)
{
Node<T>* node = new Node<T>(x);
if (NULL == _head)
{
_head = node;
_tail = node;
}
else
{
_tail->_next = node;
node->_prev = _tail;
_tail = node;
}
_sz++;
}
template<typename T>
void LinkList<T>::PopBack() //尾删
{
if (NULL == _head)
{
throw string("no data in list");
}
else if (NULL == _head->_next)
{
Release();
}
else
{
_tail = _tail->_prev;
delete _tail->_next;
_tail->_next = NULL;
_sz--;
}
}
template<typename T>
void LinkList<T>::PushFront(T x) //头插
{
Node<T>*NewNode = new Node<T>(x);
if (NULL == _head)
{
_head = NewNode;
_tail = NewNode;
}
else
{
NewNode->_next = _head;
_head->_prev = NewNode;
_head = NewNode;
}
_sz++;
}
template<typename T>
void LinkList<T>::PopFront() //头删
{
if (NULL == _head)
{
throw string("no data in list");
}
else if (NULL == _head->_next)
{
Release();
}
else
{
_head = _head->_next;
delete _head->_prev;
_head->_prev = NULL;
_sz--;
}
}
template<typename T>
Node<T>* LinkList<T>::Find(T x) //查找指定元素的地址
{
Node<T>* cur = _head;
while (cur)
{
if (cur->_data == x)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
template<typename T>
void LinkList<T>::Insert(Node<T>* node, T x) //指定位置插入指定数据
{
Node<T>* cur = _head;
Node<T>* NewNode = new Node<T>(x);
if (node == _head)
{
PushFront(x);
}
else
{
while (cur)
{
if (cur == node)
{
NewNode->_next = cur;
NewNode->_prev = cur->_prev;
cur->_prev = NewNode;
NewNode->_prev->_next = NewNode;
_sz++;
}
cur = cur->_next;
}
}
}
template<typename T>
void LinkList<T>::Remove(T x) //删除指定元素
{
Node<T>*cur = _head;
if (_head->_data == x)
{
PopFront();
}
else
{
while (cur && (cur->_data != x))
{
cur = cur->_next;
}
if (cur == NULL)
{
cout << "no such data" << endl;
}
else
{
cur->_prev->_next = cur->_next;
cur->_next->_prev = cur->_prev;
cur->_next = NULL;
cur->_prev = NULL;
delete cur;
_sz--;
}
}
}
template<typename T>
void LinkList<T>::RemoveAll(T x) //删除链表里出现的所有指定数据
{
Node<T>*cur = _head;
while (cur)
{
if ((cur->_data == x) && (cur->_next != NULL) && (cur->_prev != NULL))
{
Node<T> *del = cur;
cur = cur->_next;
del->_prev->_next = del->_next;
del->_next->_prev = del->_prev;
del->_next = NULL;
del->_prev = NULL;
delete del;
_sz--;
}
else if ((cur->_data == x) && (cur->_next == NULL))
{
//PopBack();
_tail = cur->_prev;
cur->_prev = NULL;
_tail->_next = NULL;
delete cur;
cur = NULL;
}
else if ((cur->_data == x) && (cur->_prev == NULL))
{
//PopFront();
Node<T>*del = cur;
cur = cur->_next;
_head = _head->_next;
_head->_prev = NULL;
del->_next = NULL;
delete del;
del = NULL;
}
else
cur = cur->_next;
}
}
template<typename T>
void LinkList<T>::Erase(Node<T>* node) //指定位置删除
{
Node<T>* cur = _head;
while (cur)
{
if ((cur == node) && (cur->_next != NULL) && (cur->_prev != NULL))
{
Node<T> *del = cur;
cur = cur->_next;
del->_prev->_next = del->_next;
del->_next->_prev = del->_prev;
del->_next = NULL;
del->_prev = NULL;
delete del;
_sz--;
}
else if ((cur == node) && (cur->_next == NULL))
{
_tail = cur->_prev;
cur->_prev = NULL;
_tail->_next = NULL;
delete cur;
cur = NULL;
}
else if ((cur == node) && (cur->_prev == NULL))
{
//PopFront();
Node<T>*del = cur;
cur = cur->_next;
_head = _head->_next;
_head->_prev = NULL;
del->_next = NULL;
delete del;
del = NULL;
}
else
cur = cur->_next;
}
}
template<typename T>
void LinkList<T>::BubbleSort() //冒泡排序
{
Node<T>* cur = _head;
Node<T>* EndOk = NULL;
while (cur->_next)
{
Node<T>*incur = _head;
while (incur->_next != EndOk)
{
if (incur->_data > incur->_next->_data)
{
T tmp = incur->_data;
incur->_data = incur->_next->_data;
incur->_next->_data = tmp;
}
incur = incur->_next;
}
EndOk = incur;
cur = cur->_next;
}
}
void test1()
{
LinkList<int>list;
list.PushBack(1);
list.PushBack(2);
list.PushBack(3);
list.PushBack(4);
//LinkList<int>list1(list);
cout << list << endl;
list.PopBack();
cout << list << endl;
list.PopBack();
cout << list << endl;
list.PopBack();
cout << list << endl;
try
{
list.PopBack();
}
catch (string e)
{
cout << e << endl;
}
cout << list << endl;
try
{
list.PopBack();
}
catch (string e)
{
cout << e << endl;
}
cout << list << endl;
}
void test2()
{
LinkList<int> list;
list.PushFront(1);
list.PushFront(2);
list.PushFront(3);
cout << list << endl;
try{ list.PopFront(); }
catch (string e)
{
cout << e << endl;
}
cout << list << endl;
try{ list.PopFront(); }
catch (string e)
{
cout << e << endl;
}
cout << list << endl;
try{ list.PopFront(); }
catch (string e)
{
cout << e << endl;
}
cout << list << endl;
try{ list.PopFront(); }
catch (string e)
{
cout << e << endl;
}
cout << list << endl;
}
void test3()
{
LinkList<int> list;
list.PushBack(1);
list.PushBack(2);
list.PushBack(3);
cout << list << endl;
Node<int>* ret = list.Find(3);
list.Insert(ret, 9);
cout << list << endl;
LinkList<string> list1;
list1.PushBack("ajffas");
list1.PushBack("adgadgagasdjga");
cout << list1 << endl;
LinkList<string> list2(list1);
cout << list2 << endl;
}
void test4()
{
LinkList<int> list;
list.PushBack(2);
list.PushBack(1);
list.PushBack(2);
list.PushBack(3);
list.PushBack(2);
list.PushBack(2);
cout << list << endl;
/*list.Remove(2);
cout << list << endl;*/
list.RemoveAll(2);
cout << list << endl;
}
void test5()
{
LinkList<int> list;
list.PushBack(1);
list.PushBack(2);
list.PushBack(3);
list.PushBack(4);
cout << list << endl;
/*Node<int>*ret = list.Find(2);
list.Erase(ret);*/
cout << list << endl;
}
void test6()
{
LinkList<int> list;
list.PushFront(1);
list.PushFront(2);
list.PushFront(3);
list.PushFront(4);
cout << list << endl;
list.BubbleSort();
cout << list << endl;
}
当然,模板也有利弊,虽然它复用了代码,节省资源,可以更快的迭代开发,增强了代码的灵活性。但是模板让代码变得错综复杂,不易维护,编译代码时间变长。而且,当出现错误时,错误信息非常凌乱,亲自感受一下就能知道,每次发生一个错误,真的要好久才能找到错在哪里,不易定位错误。