最近心血来潮,想把上学时学过的数据结构都自己用C++来实现一边,这是第一个——顺序栈。希望我能坚持下去。
话不多上,上代码。
首先是SeqStack.h
#ifndef SEQSTACK_H_
#define SEQSTACK_H_
#include <iostream>
#include <cstdlib>
const int DEFAULT_SIZE = 20;
template<class ElemType>
class SeqStack
{
protected:
int top;
int maxSize;
ElemType* elems;
public:
SeqStack(int size = DEFAULT_SIZE);
SeqStack(const SeqStack<ElemType>& e);
virtual ~SeqStack();
SeqStack<ElemType>& operator = (const SeqStack<ElemType>& e);
public:
int GetLength() const;
bool IsEmpty() const;
void Clear();
void Traverse();
bool Push(const ElemType e);
bool Pop(ElemType &e);
bool Top(ElemType &e) const;
};
#endif
然后是SeqStack.cpp
#include "SeqStack.h"
using namespace std;
template<class ElemType>
SeqStack<ElemType>::SeqStack(int size)
{
maxSize = size;
elems = new ElemType[maxSize];
top = -1;
}
template<class ElemType>
SeqStack<ElemType>::~SeqStack()
{
delete []elems;
}
template<class ElemType>
SeqStack<ElemType>::SeqStack(const SeqStack<ElemType>& e)
{
maxSize = e.maxSize;
delete []elems;
elems = new ElemType[maxSize];
top = e.top;
for(int i=0; i<top+1; i++)
elems[i] = e.elems[i];
}
template<class ElemType>
SeqStack<ElemType>& SeqStack<ElemType>::operator = (const SeqStack<ElemType>& e)
{
top = e.top;
maxSize = e.maxSize;
delete []elems;
elems = new ElemType[maxSize];
for(int i=0; i<=top; i++)
elems[i] = e.elems[i];
return *this;
}
template<class ElemType>
int SeqStack<ElemType>::GetLength() const
{
return top+1;
}
template<class ElemType>
bool SeqStack<ElemType>::IsEmpty() const
{
if(-1 == top)
{
return true;
}else{
return false;
}
}
template<class ElemType>
void SeqStack<ElemType>::Clear()
{
top = -1;
}
template<class ElemType>
void SeqStack<ElemType>::Traverse()
{
for(int i = top; i>=0; i--)
cout << elems[i] << " ";
cout << endl;
}
template<class ElemType>
bool SeqStack<ElemType>::Push(const ElemType e)
{
if(maxSize == top+1)
return false;
top++;
elems[top] = e;
return true;
}
template<class ElemType>
bool SeqStack<ElemType>::Top(ElemType& e) const
{
if(IsEmpty())
return false;
e = elems[top];
return true;
}
template<class ElemType>
bool SeqStack<ElemType>::Pop(ElemType& e)
{
if(IsEmpty())
return false;
e = elems[top];
top--;
return true;
}
再最后是我的测试代码:
#include "SeqStack.cpp"
using namespace std;
int main()
{
SeqStack<int> stack;
int choice = 1;
int ipt = 1;
int opt;
while(choice != 0)
{
cout << "select functions(0~6):" << endl;
cout << "1.Construct Stack" << " " << "2.Show the Stack" << endl;
cout << "3.Clear the Stack" << " " << "4.Get top of the Stack" << endl;
cout << "5.Push " << " " << "6.Pop" << endl;
cout << "0.Exit" << endl;
cin >> choice;
switch(choice)
{
case 1 :
{
stack.Clear();
cout << "stop by 0" << endl;
cin >> ipt;
while(ipt != 0)
{
if(!stack.Push(ipt))
{
cout << "The stack is fulled" << endl;
break;
}
cin >> ipt;
}
cin.clear();
break;
}
case 2 :
{
stack.Traverse();
break;
}
case 3 :
{
stack.Clear();
break;
}
case 4 :
{
stack.Top(opt);
cout << "the top of the stack: " << opt << endl;
break;
}
case 5 :
{
cin >> ipt;
if(!stack.Push(ipt))
cout << "The stack is fulled" << endl;
cout << "push successed" << endl;
cin.clear();
break;
}
case 6 :
{
if(!stack.Pop(opt))
cout << "The stack is empty" << endl;
cout << "Pop successed" << endl;
break;
}
default :
break;
}
}
cout << "bye" << endl;
return 0;
}
接下来我要讲一下关于C++模板类的东西了。
首先上面的代码是没有什么问题的,但是结构是有问题的。你们可能注意到了我main.cpp中包含的是SeqStack.cpp而不是.h文件。这样子包含其实就相当于模板类的实现和声明其实是在一个文件里了。为什么要这样呢?
这是我作为一个刚开始编写模板类代码的人犯的一个经典的错误。模板就像它的名字一样,就是一个模板!它和我们经常接触的类和成员函数定义不一样,它们是C++编译器指令,说明了如何生成类和成员函数定义!
模板的具体实现被称为——实例化:
SeqStack<int> stack;
我们不能将模板成员函数放在独立的实现文件中,是因为模板不是函数!模板不是函数!模板不是函数!它们不能单独编译,它们必须和特定的模板实例化请求一起使用,所以最简单的方法就是将所有模板的信息放在一个头文件中。
然后再讲讲模板类相对于C中的typedef的好处,即typedef的两个缺点:
- 每次修改类型时,都需要修改头文件
- 每个程序中只能使用这种方法生成一种栈,我无法同时在一个程序中生成int型的和char型的栈