模板是泛型编程的基础。
所谓泛型编程就是编写与类型⽆关的逻辑代码,是⼀种复⽤的⽅式。
模板分为模板函数和模板类。
函数模板格式:
template <class 形参名1, class 形参名2, class 形参名n>
返回类型 函数名(参数列表)
{
...
}
模板形参的定义既可以使⽤class,也可以使⽤typename,含义是相同的。
注:模板未实例化时,代码内部的语法错误检测不到。
双向循环链表
链表分为有头结点和无头结点,单向和双向,循环和不循环
这里实现一个有头结点的双向循环链表
#include<iostream>
#include<windows.h>
#include<assert.h>
using namespace std;
template<class T>
struct ListNode
{
T _data;
ListNode<T>* _next;
ListNode<T>* _prev;
ListNode(const T& x=T())
:_data(x)
, _next(NULL)
, _prev(NULL)
{}
};
template<class T>
class List
{
typedef ListNode<T> Node;
public:
List()
{
_head = new Node;
_head->_prev = _head;
_head->_next = _head;
}
//传统写法
List(const List<T> &l)
{
_head = new Node(T());
_head->_next = _head;
_head->_prev = _head;
Node*cur = l._head->_next;
while (cur != l._head)
{
PushBack(cur->_data);
cur = cur->_next;
}
}
//现代写法
List<T>&operator=(List<T> l)
{
swap(_head, l._head);
return *this;
}
~List()
{
Clear();
delete _head;
}
void Clear()//不清除头结点
{
Node*cur = _head->_next;
while (cur != _head)
{
Node*del = cur;
cur = cur->_next;
delete del;
}
_head->_next = _head;
_head->_prev = _head;
}
//增删查改
void PushBack(const T&x)
{
//Node*tail = _head->_prev;//找到尾结点
//Node*tmp = new Node(x);//创建新节点
//_head->_prev = tmp;
//tmp->_next = _head;
//tail->_next = tmp;
//tmp->_prev = tail;
Insert(_head, x);
}
void PopBack()
{
//assert(_head->_next != _head);//断言
//Node*tail = _head->_prev;//找到尾结点
//Node*prev = tail->_prev;//找到尾结点的前一个结点
//delete tail;//删除尾结点
//_head->_prev = prev;//头结点的前一个结点为prev
//prev->_next = _head;//prev的后一个结点为_head
Erase(_head->_prev);
}
void PopFront()
{
//assert(_head->_next != _head);
//Node*tmp = _head->_next;
//Node*next = tmp->_next;
//delete tmp;
//
//_head->_next = next;
//next->_prev = _head;
Erase(_head->_next);
}
void PushFront(const T&x)
{
//Node*tmp = new Node(x);
//Node*next = _head->_next;
//_head->_next = tmp;
//tmp->_prev = _head;
//tmp->_next = next;
//next->_prev = tmp;
Insert(_head->_next, x);
}
bool Empty()//判断是否为空
{
return _head->_next == _head;
}
void Print()
{
Node*cur = _head->_next;
while (cur!= _head)
{
cout << cur->_data << "";
cur = cur->_next;
}
cout << endl;
}
void Erase(Node*pos)
{
assert(pos&&pos != _head);
Node* prev = pos->_prev;
Node* next = pos->_next;
delete pos;
prev->_next = next;
next->_prev = prev;
}
void Insert(Node*pos, const T&x)
{
assert(pos);
Node*tmp = new Node(x);
Node*prev = pos->_prev;
prev->_next = tmp;
tmp->_prev = prev;
tmp->_next = pos;
pos->_prev = tmp;
}
Node* Find(const T &x)
{
Node*cur = _head->_next;
while (cur!=_head)
{
if (cur->_data == x)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
protected:
Node* _head;
};
顺序表
template<class T>
class Seqlist
{
public:
Seqlist()
:_a(NULL)
, _capacity(0)
, _size(0)
{}
Seqlist(Seqlist & s)
:_a(s._a)
, _capacity(s._capacity)
, _size(s._size)
{}
Seqlist& operator=(Seqlist&s)
{
swap(_a, s._a);
swap(_capacity, s._capacity);
swap(_size, s.size);
return *this;
}
void CheakCapacity()
{
if (_size == _capacity)
{
size_t Newsize = _size ? _capacity * 2 : 3;
_a = (T*)realloc(_a, Newsize*sizeof(T));
_capacity = Newsize;
}
}
void PushBack(const T &x)
{
CheakCapacity();
_a[_size++] = x;
}
void PopBack()
{
assert(_size);
--_size;
}
void PushFront(const T &x)
{
CheakCapacity();
int end = _size;
while (end>0)
{
_a[end] = _a[end - 1];
end--;
}
_a[0] = x;
++_size;
}
void PopFront()
{
assert(_a);
int n = 0;
while (n<_size-1)
{
_a[n] = _a[n + 1];
n++;
}
--_size;
}
~SeqList()
{
if (_a)
{
free(_a);
}
}
void Print()
{
for (size_t i = 0; i < _size; i++)
{
cout << _a[i] << " ";
}
cout << endl;
}
private:
T *_a;
size_t _capacity;
size_t _size;
};
本文探讨了泛型编程的概念,强调模板在其中的重要作用。内容包括模板函数和模板类的介绍,以及如何利用C++模板实现一个有头结点的双向循环链表,讲解链表的分类,并提供了顺序表的相关知识。

339

被折叠的 条评论
为什么被折叠?



