下面介绍模板类来实现静态顺序表和栈,顺序栈(seqential stack)就是用顺序存储方式存储的栈。在下面顺序栈的类定义中是用数组存储的,用_array[]存储,_size是实际存放的个数,_capacity是最大允许存放元素的个数,变量top表示栈顶部元素的位置。由于栈是后进先出原则,所以可以通过调用顺序表实现进栈和出栈等操作,Container<T>为“容器”,利用模板的模板参数--容器适配器调用顺序表。

下面用模板实现了顺序表的头插、尾插、头删、尾删、请求空间及增删查改等操作。

如下所示:

#pragma once

#include<string>
#include<assert.h>

template <class T>
class SeqList
{
public:
	SeqList()
		:_array(NULL)
		, _size(0)
		, _capacity(0)
	{}
	SeqList(const SeqList<T>& s)
		:_array(new T[s._size])
		,_size(s._size)
	    ,_capacity(s._size)
	{
		for (size_t i = 0; i < _size; i++)
		{
			_array[i] = s._array[i];
		}
	}
	SeqList<T>& operator=(SeqList<T>& s)
	{
		if (this != &s)
		{
			swap(_array, s._array);
			swap(_size, s._size);
			swap(_capacity, s._capacity);
		}
		return *this;
	}
	~SeqList()
	{
		if (_array)
		{
			delete[] _array;
		}
	}
public:
	void CheckCapacity(size_t n);
	void Reserve(size_t n);//请求空间
	void PrintSeqList();
	void PushBack(const T& x)//尾插
	{
		CheckCapacity(_size + 1);//检查增加一个后的容量
		_array[_size++] = x;
	}
	void PopBack()//尾删
	{
		if (_size > 0)
			_array[_size--] = '0';
	}
	void PushFront(const T& x)//头插
	{
		CheckCapacity(_size + 1);
		if (_size > 0)
		{
			for (size_t i = _size; i > 0; i--)
			{
				_array[i] = _array[i - 1];
			}
		}
		_array[0] = x;
		_size++;
	}
	void PopFront()//头删
	{
		if (_size > 0)
		{
			for (size_t i = 0; i < _size; i++)
			{
				_array[i] = _array[i + 1];
			}
			_size--;
		}
	}
	size_t Find(const T& x)//查找x
	{
		for (size_t i = 0; i < _size; i++)
		{
			if (x == _array[i])
				return i + 1;
		}
		return -1;
	}
	void Insert(size_t pos, const T& x)//在pos处添加x
	{
		assert(pos);
		if (pos == _size)
			SeqList<T>::PushBack(x);
		else
		{
			CheckCapacity(_size + 1);
			for (size_t i = _size; i > pos - 1; i--)
			{
				_array[i] = _array[i - 1];
			}
			_size++;
			_array[pos - 1] = x;
		}
	}
	void Erase(size_t pos)
	{
		assert(pos);
		if (pos == _size)
			SeqList<T>::PopBack();
		else
		{
			for (size_t i = pos - 1; i < _size; i++)
			{
				_array[i] = _array[i + 1];
			}
			_size--;
		}
	}
	size_t Size()
	{
		return _size;
	}
	T& Top()
	{
		return _array[_size-1];
	}
public:
	T* _array;
	size_t _size;
	size_t _capacity;
};

//类外定义
template<typename T>//模板类的类型是SeqList<T>
void SeqList<T>::CheckCapacity(size_t n)//扩容
{
	if (n > _capacity)
	{
		_capacity = n > 2 * _capacity + 3 ? n : (2 * _capacity + 3);
		//_array = (T*)realloc(_array, sizeof(T)*_capacity);
		//当T为string等自定义类型时,会发生错误。由于malloc,realloc都没有调用构造函数初始化对象,产生随机值
		T*tmp = new T[_capacity];//开辟空间大小为_capacity
		if (_array)
		{
			//memcpy(tmp, _array, sizeof(T)*_size);//vs2008中对于长字符串会析构两次造成崩溃,vs2013中长短字符串在析构时都会崩溃
			for (size_t i = 0; i < _size; i++)
			{
				tmp[i] = _array[i];
			}
		}
		delete[] _array;
		_array = tmp;
	}
}

template<typename T>
void SeqList<T>::Reserve(size_t n)//请求空间-保存
{
	SeqList<T>::CheckCapacity(n);
}

template<typename T>
void SeqList<T>::PrintSeqList()//打印顺序表
{
	if (_size <= 0)
	{
		cout << "SeqList is empty!" << endl;
	}
	else
	{
		for (size_t i = 0; i < _size; i++)
			cout << _array[i] << "-";
		cout << "NULL" << endl;
	}
}

顺序栈的实现进栈、出栈、判空、栈顶及栈中元素个数等操作

//C++栈的实现(模板)
//模板参数--实现容器适配器
//template<class T,class Container>//此写法对于Stack<int,SeqList<char>>s;易造成数据丢失
//template<class T,class Container=SeqList<T>>
//模板的模板参数--容器适配器
template<class T, template<class> class Container = SeqList>//template<class T, template<class T> class Container = SeqList>
class Stack
{
public:
	void Push(const T& x)
	{
		_con.PushBack(x);
	}
	void Pop()
	{
		_con.PopBack();
	}
	bool Empty()
	{
		return _con.Size() == 0;
	}
	size_t Size()
	{
		return _con.Size();
	}
	T& Top()//栈顶
	{
		return _con.Top();
	}
	void PrintStack()
	{
		_con.PrintSeqList();
	}
protected:
	//Container _con;
	Container<T> _con;
};

顺序表及顺序栈的测试用例如下:

#include<iostream>
using namespace std;

#include"SeqList.h"

void Test1()
{//尾插尾删,赋值,构造
	SeqList<int> s1;
	s1.PushBack(1);
	s1.PushBack(2);
	s1.PushBack(3);
	s1.PushBack(4);
	s1.PrintSeqList();

	SeqList<string> s2;
	//cout << sizeof(string) << endl;//28
	s2.PushBack("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
	s2.PushBack("sssss");
	s2.PushBack("fffff");
	s2.PushBack("ggggg");
	s2.PrintSeqList();

	//s2.PopBack();
	//s2.PopBack();
	//s2.PrintSeqList();
	//s2.PopBack();
	//s2.PopBack();
	//s2.PopBack();
	//s2.PrintSeqList();

	SeqList<string> s3(s2);
	s3.PrintSeqList();
	SeqList<string> s4;
	s4 = s2;
	s4.PrintSeqList();

	s2.Reserve(1000);//请求空间保存
	cout << s2._capacity << endl;
}

void Test2()
{//头插头删
	SeqList<int> s1;
	s1.PushFront(1);
	s1.PushFront(2);
	s1.PushFront(3);
	s1.PushFront(4);
	s1.PrintSeqList();

	SeqList<string> s2;
	s2.PushFront("xxxxxx");
	s2.PushFront("yyyyyy");
	s2.PushFront("zzzzzz");
	s2.PushFront("gggggg");
	s2.PrintSeqList();

	s2.PopFront();
	s2.PopFront();
	s2.PrintSeqList();
	s2.PopFront();
	s2.PopFront();
	s2.PopFront();
	s2.PrintSeqList();

}

void Test3()
{//头插头删
	SeqList<int> s1;
	s1.PushBack(1);
	s1.PushBack(2);
	s1.PushBack(3);
	s1.PushBack(4);
	s1.PrintSeqList();

	SeqList<string> s2;
	s2.PushBack("xxxxxx");
	s2.PushBack("gggggg");
	s2.PushBack("zzzzzz");
	s2.PushBack("ffffff");
	s2.PrintSeqList();

	cout << s2.Find("gggggg") << endl;
	s2.Insert(2, "yyyyyy");
	s2.PrintSeqList();
	s2.Erase(3);
	s2.PrintSeqList();
}
void Test4()
{//顺序栈
	//Stack<int, SeqList<int>>s1;
	//Stack<int>s2;
	//Stack<int> s1;
	//s1.Push(0);
	//s1.Push(1);
	//s1.Push(2);
	//s1.Push(3);
	Stack<string> s1;
	s1.Push("xxxxxx");
	s1.Push("yyyyyy");
	s1.Push("zzzzzz");
	s1.Push("gggggg");

	cout << s1.Empty() << endl;
	cout << "size->" << s1.Size() << endl;
	string top = s1.Top();
	cout << "top->" << top << endl;
	//访问栈中元素
	while (!s1.Empty())
	{
		cout << s1.Top() << "-";
		s1.Pop();
	}
	cout << endl;
	s1.Pop();
	s1.PrintStack();
	s1.Pop();
	s1.Pop();
	s1.PrintStack();
}