顺序栈的实现与解析
顺序栈
顺序栈,即栈的顺序存储结构利用一组地址连续的存储单元依次存放自栈低到栈顶的数据元素,同时附设指针top指向栈顶元素在顺序栈中的位置。栈的特性,先进后出,后进先出,推荐可以看一看电影盗梦空间,跟函数的调用顺序有关系
栈顶
表示栈的线性表的表尾端
栈底
表示栈的线性表的表头端
基本操作
1.进栈
2.退栈
3.得到栈顶元素
5.栈的初始化和销毁
代码实现
头文件
#ifndef MYSTACK_H
#define MYSTACK_H
#include <iostream>
#include <stdexcept>
using namespace std;
//顺序栈的实现与解析
template <typename Type>
class MyStack
{
//声明为友元函数,可以直接在类外部使用
template <typename T>
friend ostream &operator <<(ostream &os,const MyStack<T> &stack);
public:
MyStack(int stackCapacity = 16);
~MyStack();
/*非静态成员函数后面加const,表示成员函数隐含传入的this指针为const指针,
*决定了在该成员函数中,任意修改它所在类的成员的操作是不允许的,增加了代码的可维护性
**/
//判断栈是否为空
bool isEmpty() const;
/*
* const在*前面表示这是一个字符串常量指针,它所指向的变量值不能被修改,但是这个指针的指向变量的地址可以改变
* const在*的后面,则表示这是一个指针常量,它指向的变量值不能被修改,但可以修改他所指向的变量的地址
* */
//进栈
void push(const Type &item);
//退栈
void pop() throw(std::range_error); //表示pop只能抛出range_error类型的异常 range_error:内部计算时发生区间错误时抛出
/*
* 在函数之前加const修饰了返回值,加&表示对函数返回值的引用
**/
//返回栈顶元素
const Type &top() const throw(std::range_error);
private:
Type *m_stack;
int m_top; //栈顶指针
int m_capacity; //表示栈顶容量
};
#endif // MYSTACK_H
源文件
#include "mystack.h"
//构造函数
template <typename Type>
MyStack<Type>::MyStack(int stackCapacity):m_capacity(stackCapacity)
{
if(m_capacity<1)
throw range_error("new size must >= 1");
//申请内存并构造对象
m_stack = new Type[m_capacity];
if(m_stack == NULL)
throw bad_alloc(); //new 操作失败时会抛出
m_top = -1;
}
//析构函数
template <typename Type>
MyStack<Type>::~MyStack()
{
//析构内存并释放对象
delete []m_stack;
m_top = -1; //将top指针指向无效
m_capacity = 0;
}
// "*&"为指针引用,可以修改指针里存放的地址
//改变数组大小,扩大二倍
template <typename Type>
static void changeSize(Type *&array,int oldSize,int newSize)
throw(range_error,bad_alloc)
{
if(newSize < 0)
throw range_error("new size must >= 0");
Type *tmp = new Type[newSize];
if(tmp == NULL)
throw bad_alloc();
int minSize = std::min(oldSize,newSize);
std::copy(array,array+minSize,tmp);
delete []array; //将原数组释放掉
array = tmp; //将原指针指向新申请的数组
}
//进栈
template <typename Type>
void MyStack<Type>::push(const Type &item)
{
//数组最大容量为m_capacity,因此数组最大下标为m_capacity-1
if(m_top >= m_capacity-1)
{
//一次扩容2倍
changeSize(m_stack,m_capacity,m_capacity*2);
m_capacity *=2;
}
m_stack[++m_top] = item;
}
//栈是否为空
template <typename Type>
bool MyStack<Type>::isEmpty() const
{
return -1 == m_top;
}
template <typename Type>
const Type &MyStack<Type>::top() const
throw(std::range_error)
{
if(isEmpty())
throw range_error("stack is empty");
return m_stack[m_top];
}
//出栈
template <typename Type>
void MyStack<Type>::pop()
throw(range_error)
{
if(isEmpty())
throw range_error("stack is empty");
//如果该栈保存的对象类型的元素,则需要显示调用其析构函数
//同时还需要将栈顶指针下移
m_stack[m_top--].~Type();
}
//输出栈的所有内容,以便调试,重载运算符<<
template <typename Type>
ostream &operator <<(ostream &os,const MyStack<Type> &stack)
{
os << stack.m_stack[0];
for(int i=1;i <= stack.m_top; ++i)
os << ' '<< stack.m_stack[i];
return os;
}
main函数
#include <iostream>
#include <stdexcept>
#include "mystack.h"
#include "mystack.cpp"
using namespace std;
int main()
{
MyStack<int> myStack;
myStack.push(10);
myStack.push(22);
myStack.push(15);
cout << myStack <<endl;
try
{
cout << "Top = " << myStack.top() << endl;
myStack.pop();
cout << "Top = " << myStack.top() << endl;
myStack.pop();
cout << "Top = " << myStack.top() << endl;
myStack.pop();
cout << "Top = " << myStack.top() << endl;
}
catch (const std::exception &e)
{
cout << e.what() << endl;
}
return 0;
}