用模板写链表主要还是为了实现代码的类型通用性,用模板写函数或类都与是类型无关的,因此,STL中都是用模板来实现容器,下面我们来介绍用模板实现顺序表和带头结点的双向循环链表。 以下代码将实现顺序表和链表的增、删、查、改、判空等常用接口以做练习。
顺序表
#pragma once
template<class T>
class SeqList
{
public:
SeqList()
:_a(NULL)
, _size(0)
, _capacity(0)
{};
SeqList(const SeqList<T>&s)//构造
{
_a = new T[s.size];
for (size_t i = 0; i < s.size; ++i){
_a[i] = s._a[i];
}
_size = s.size;
_capacity = s.size;
}
SeqList<T>& operator = (SeqList<T> S) {//赋值运算符重载
swap(_a, s._a);
swap(_size, s._size);
swap(capacity, s._capacity);
return *this;
}
//析构
~SeqList(){
if (_a){
delete[] _a;
}
}
void PushBack(const T& x)
{
CheckCapacity();
_a[_size++] = x;//operatpr =
}
void PopBack() {
assert(_size > 0);
--_size;
}
size_t GetSize() {
return _size;
}
bool IsEmpty()
{
return _size == 0;
}
T& GetBackElement()
{
assert(_size > 0);
return _a[size - 1];
}
//void Insert(size_t pos, const T& x);
//void Erase(size_t pos);
//size_t find(const T& x);
void CheckCapacity()
{
if (_size == _capacity)
{
size_t newSize = _capacity ? _capacity * 2 : 3;//如果_capacity存在扩容2倍,置容量为3.
T* tmp = new T[newSize];//临时新顺序表
for (size_t i = 0; i < _size; ++i)//逐个拷贝至临时tmp中暂时存放
{
tmp[i] = _a[i];
}
delete[] _a;//释放回收旧表
_a = tmp;//将tmp存放节点们赋给
_capacity = newSize;
assert(_a);//确保拷贝成功 _a不为空
}
}
void print() {
for (size_t i = 0; i < _size; i++)
{
cout << _a[i] << " "<<endl;
}
cout << endl;
}
protected:
T * _a;
size_t _size;
size_t _capacity;
};
带头结点的循环双向链表
#pragma once
template<typename T>
struct ListNode
{
ListNode<T>* _next;
ListNode<T>* _prev;
T _data;
ListNode(const T& x)
:_next(NULL)
,_prev(NULL)
,_data(x)
{}
};
// 带头结点的双向循环链表
template<class T>
class List
{
typedef ListNode<T> Node;
public:
List()
{
_head = new Node(T());
_head->_next = _head;
_head->_prev = _head;
}
// l2(l1)
List(const List<T>& l)
{
_head = new Node(T());
_head->_next = _head;
_head->_prev = _head;
Node* cur = l._head->_next;
while (cur != l._head)
{
this->PushBack(cur->_data);
cur = cur->_next;
}
}
List<T>& operator=(List<T> l)
{
swap(_head, l._head);
return *this;
}
~List()
{
Clear();
delete _head;
_head = NULL;
}
void Clear()
{
Node* cur = _head->_next;
while (cur != _head)
{
/* Node* next = cur->_next;
delete cur;
cur = next;*/
Node* del = cur;
cur = cur->_next;
delete del;
}
_head->_next = _head;
_head->_prev = _head;
}
void PushBack(const T& x)
{
Insert(_head, x);
}
void PopBack()
{
Erase(_head->_prev);
}
void PopFront()
{
Erase(_head->_next);
}
void PushFront(const T& x)
{
Insert(_head->_next, x);
}
void Insert(Node* pos, const T& x)
{
assert(pos);
Node* prev = pos->_prev;
Node* tmp = new Node(x);
// prev tmp pos
prev->_next = tmp;
tmp->_prev = prev;
tmp->_next = pos;
pos->_prev = tmp;
}
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 Print()
{
Node* cur = _head->_next;
while (cur != _head)
{
cout<<cur->_data<<" ";
cur = cur->_next;
}
cout<<endl;
}
T& Back()
{
assert(!Empty());
return _head->_prev->_data;
}
const T& Front()
{
assert(!Empty());
return _head->_next->_data;
}
inline bool Empty()
{
return _head->_next == _head;
}
size_t Size()
{
size_t size = 0;
Node* cur = _head->_next;
while (cur != _head)
{
++size;
cur = cur->_next;
}
return size;
}
protected:
Node* _head;
};
//void TestList1()
//{
// List<int> l;
// l.PushBack(1);
// l.PushBack(2);
// l.PushBack(3);
// l.PushBack(4);
//
// l.PopBack();
// l.PopBack();
// l.PopBack();
// l.PopBack();
// l.Print();
//}
void TestList2()
{
List<int> l;
l.PushBack(1);
l.PushBack(2);
l.PushBack(3);
l.PushBack(4);
List<int> l2(l);
l2.Print();
}
测试顺序表,链表
#include<iostream>
#include<string>
#include<assert.h>
#include<windows.h>
#include "SeqList.h"
#include "List.h"
using namespace std;
void TestSeqList()
{
//SeqList<int> s1;
//s1.PushBack(1);
//s1.PushBack(2);
//s1.PushBack(3);
//s1.PushBack(4);
//s1.PushBack(5);
//s1.print();
SeqList<string>s2;
s2.PushBack("Still");
s2.PushBack("Still is pig!!");
s2.PushBack("What a foolish Still!");
s2.PushBack("Stillis a pig forever!");
s2.print();
//SeqList<string> s3(s2);
//s3.print();
}
int main()
{
TestSeqList();
//TestList2();
system("pause");
return 0;
}