读前声明:本人所写帖子主要为了记录本人学习的一个过程,无他想法,由于内容比较肤浅,如有雷同,非常正常!!!
本文内容:
栈是一种最常用和最重要的数据结构,它的用途非常广泛。例如,汇编处理程序中的句法识别和表达式计算就是基于栈实现的。栈还经常使用在函数调用时的参数传递和函数值的返回方面。
通常,栈可定义为只允许在表的末端进行插入和删除的线性表。允许插入和删除的一端叫做栈顶,而不允许插入和删除的另一端叫栈底。当栈没有任何元素是则称为空栈,其特性即为后进先出(Last In First Out)。
其栈的抽象数据类如下:
template <class T>
class Stack
{
public:
Stack(){}; //构造函数
virtual void Push(const T& x) = 0; //新元素x进栈
virtual bool Pop(T& x) = 0; //栈顶元素出栈,由x返回
virtual bool getTop(T& x)const = 0; //读取栈顶元素,由x返回
virtual bool IsEmpty()const = 0; //判断栈是否空
virtual bool IsFull()const = 0; //判断栈是否满
// virtual int getSize() const = 0; //计算栈中元素个数
};
栈的抽象数据类型有两种典型的存储表示:基于数组的存储表示和基于链表的存储表示。基于数组的存储表示实现的栈为顺序栈,基于链表的存储表示实现的栈称为链式栈。
1、顺序栈
类定义
#include <assert.h>
#include <iostream>
#include "stack.h"
using namespace std;
const int stackIncreament = 20; //栈溢出时扩展空间的增量
template <class T>
class SeqStack: public Stack<T>
{
public:
SeqStack(int sz=50);
~SeqStack(){delete []elements;}
void Push(const T& x); //如果栈满了,则溢出处理;若没满,就将数据插入栈顶
bool Pop(T& x); //如果栈空,则不执行退栈,返回false;否则退掉位于栈顶的元素,返回true;退出的元素通过引用型参数x返回
bool getTop(T& x)const; //如果栈空,返回false;否则返回true;并通过引用型参数x得到栈顶元素的值
bool IsEmpty()const{return (top==-1)?true:false;}
bool IsFull()const{return (top==maxSize-1)?true:false;}
int getSize()const{return top+1;}
void MakeEmpty(){top=-1;}
friend ostream& operator<<<T>(ostream &os,SeqStack<T> &s);
private:
T *elements;
int top;
int maxSize;
void OverflowProcess();
};
类的成员函数定义:
template <class T>
SeqStack<T>::SeqStack(int sz):top(-1),maxSize(sz)
{
elements = new T[maxSize];
assert(elements!=NULL);
};
template <class T>
void SeqStack<T>::OverflowProcess()
{
T *newArray = new T[maxSize+stackIncreament];
if (newArray==NULL)
{
cout<<"存储分配失败"<<endl;
exit(1);
}
for (int i=0;i<=top;i++)
{
newArray[i] = elements[i];
}
maxSize = maxSize + stackIncreament;
delete []elements;
elements = newArray;
};
template <class T>
void SeqStack<T>::Push(const T& x)
{
if (IsFull()==true)
{
OverflowProcess();
}
elements[++top] = x;
};
template <class T>
bool SeqStack<T>::Pop(T& x)
{
if (IsEmpty()==true)
{
return false;
}
x = elements[top--];
return true;
};
template <class T>
bool SeqStack<T>::getTop(T& x)const
{
if (IsEmpty()==true)
{
return false;
}
x = elements[top];
return true;
};
template <class T>
ostream& operator<<(ostream &os,SeqStack<T> &s)
{
os<<"top ="<<s.top<<endl;
for (int i=0;i<=s.top;i++)
{
os<<i<<":"<<s.elements[i]<<endl;
}
return os;
};
2、链式栈
链式栈是线性表的链接存储方式,采用链式栈来表示一个栈,便于结点的插入与删除。链式栈的栈顶在链表的表头,因此新结点的插入和栈顶结点的删除都是在链表的表头,即栈顶进行。
首先引入链表结点模板类:
template <class T>
struct LinkNode
{
T data; //数据域
LinkNode<T> *link; //链指针域
LinkNode(LinkNode<T> *ptr=NULL) {link = ptr;} //构造函数
LinkNode(const T &item,LinkNode<T> *ptr=NULL)
{
data = item;
link = ptr;
}
};
链式栈的类定义
template <class T>
class LinkedStack:public Stack<T>
{
public:
LinkedStack():top(NULL){}
~LinkedStack(){makeEmpty();}
void Push(const T& x); //进栈
bool Pop(T& x); //退栈
bool getTop(T& x)const; //读取栈顶元素
bool IsEmpty()const{return (top==NULL)? true:false;}
int getSize()const; //计算元素个数
void makeEmpty(); //清空栈内内容
friend ostream& operator<<<T>(ostream& os,LinkedStack<T>& s);
private:
LinkNode<T> *top; //栈顶指针
};
链式栈的成员函数定义:
template <class T>
void LinkedStack<T>::makeEmpty()
{
//逐次删去栈中的元素直至栈顶指针为空
LinkNode<T> *p;
while (top!=NULL)
{
p = top;
top = top->link;
delete p;
}
};
template <class T>
bool LinkedStack<T>::Pop(T& x)
{
if (IsEmpty()==true)
{
return false;
}
LinkNode<T> *p = top;
top = top->link;
x = p->data;
delete p;
return true;
};
template <class T>
void LinkedStack<T>::Push(const T& x)
{
top = new LinkNode<T>(x,top);
assert(top!=NULL);
};
template <class T>
bool LinkedStack<T>::getTop(T& x)const
{
if (IsEmpty()==true)
{
return false;
}
x = top->data;
return true;
};
template <class T>
int LinkedStack<T>::getSize()const
{
int size=0;
LinkNode<T> *p=top;
while (p!=NULL)
{
p = p->link;
size++;
}
delete p;
return size;
};
template <class T>
ostream & operator<<(ostream& os,LinkedStack<T>& s)
{
os<<"栈的元素个数为:"<< s.getSize()<<endl;
LinkNode<T> *p = s.top;
int i = 0;
while (p!=NULL)
{
os<<++i<<":"<<p->data<<endl;
p = p->link;
}
return os;
}