顺序栈
1.1 栈的抽象数据类型
1.2 顺序栈的类定义
1.3 构造函数
1.4 析构函数
1.5 栈溢出处理函数
1.6 进栈操作
1.7 出栈操作
1.8 取栈顶操作循环队列
5.1 首尾结合的实现
5.2 "空"" 满 " 问题的实现
5.3 判满操作
5.4 计算元素个数链式队列
6.1 链式队列结点类定义
6.2 链式队列类定义
6.3 入队操作
6.4 出队操作
6.5 取队头元素操作
6.6 析构函数
# 一、顺序栈
# 1. 栈的抽象数据类型
// 栈的抽象数据类型 | |
template<class T> | |
class Stack // 栈的类定义 | |
{ | |
Stack(); // 构造函数 | |
virtual void Push(T x)=0; // 进栈 | |
virtual bool Pop(T &x)=0; // 出栈 | |
virtual bool getTop(T &x)=0; // 取栈顶 | |
virtual bool IsEmpty()=0; // 判栈空 | |
virtual bool IsFull()=0; // 判栈满 | |
}; |
# 2. 顺序栈的类定义

template<class T> | |
class SeqStack // 顺序栈类定义 | |
{ | |
T *elements; // 栈元素存放数组 | |
int top; // 栈顶指针 | |
int maxSize; // 栈最大容量 | |
void overflowProcess(); // 栈的溢出处理 | |
public: | |
SeqStack(int sz=50); // 构造函数 | |
~SeqStack(); // 析构函数 | |
void Push(T x); // 进栈 | |
bool Pop(T &x); // 出栈 | |
bool getTop(T &x); // 取栈顶内容 | |
bool IsEmpty() const | |
{ | |
return top==-1; | |
} | |
bool IsFull() const | |
{ | |
return top==maxSize-1; | |
} | |
}; |
# 3. 构造函数
template<class T> | |
SeqStack<T>::SeqStack(int sz) : maxSize(sz)// 构造函数 | |
{ | |
top=-1; | |
elements=new T[maxSize]; | |
assert(elements!=NULL);// 判断是否分配成功 | |
} |
# 4. 析构函数
template<class T> | |
SeqStack<T>::~SeqStack()// 析构函数 | |
{ | |
delete []elements; | |
} |
# 5. 栈溢出处理函数
template<class T> | |
void SeqStack<T>::overflowProcess()// 栈溢出处理函数 | |
{ | |
// 当栈满,则执行扩充栈存储空间处理 | |
T *newArray=new T[2*maxSize];// 创建更大的存储数组 | |
for(int i=0;i<=top;++i) | |
{ | |
newArray[i]=elements[i]; | |
} | |
maxSize+=maxSize; | |
delete []elements; | |
elements=newArray;// 改变 elements 指针 | |
} |
# 6. 进栈操作

template<class T> | |
void SeqStack<T>::Push(T x)// 进栈操作 | |
{ | |
if(IsFull()==true)// 栈满 -> 扩充 | |
{ | |
overflowProcess(); | |
} | |
elements[++top]=x;// 栈顶指针先 + 1,再进栈 | |
} |
# 7. 出栈操作

template<class T> | |
bool SeqStack<T>::Pop(T &x)// 出栈操作 | |
{ | |
if(IsEmpty()==true) | |
{ | |
return false; | |
} | |
x=elements[top--];// 栈顶指针 - 1 | |
return true;// 退栈成功 | |
} |
# 8. 取栈顶操作
template<class T> | |
bool SeqStack<T>::getTop(T &x)// 取栈顶操作 | |
{ | |
if(IsEmpty()==true)// 若栈不空,则函数返回该栈栈顶元素的地址 | |
{ | |
return false; | |
} | |
x=elements[top]; | |
return true; | |
} |
以上算法时间复杂度均为 O (1)
# 二、链式栈
# 1. 链式栈类的定义

template<class T> | |
struct StackNode// 栈结点类定义 | |
{ | |
public: | |
T data; // 栈结点数据 | |
StackNode<T> *link; // 结点链指针 | |
StackNode(T d=0,StackNode<T> *next=NULL) : data(d),link(next){}// 构造函数 | |
}; | |
template<class T> | |
class LinkedStack// 链式栈类定义 | |
{ | |
private: | |
StackNode<T> *top; // 栈顶指针 | |
void output(ostream *os,StackNode<T> *ptr,int i);// 递归输出栈的所有元素 | |
public: | |
LinkedStack() : top(NULL){} // 构造函数 | |
~LinkedStack() // 析构函数 | |
{ | |
makeEmpty(); | |
} | |
void Push(T x);// 进栈 | |
bool Pop(T &x);// 出栈 | |
bool getTop(T &x) const;// 取栈顶 | |
bool IsEmpty() const | |
{ | |
return top==NULL; | |
} | |
void makeEmpty();// 清空栈的内容 | |
friend osetream &operator<<(ostream &os,LinkedStack<T> &s)// 输出栈元素的重载操作 & lt;< | |
{ | |
output(os,s.top,1); | |
} | |
}; |
# 2. 清空操作
template<class T> | |
void LinkedStack<T>::makeEmpty()// 清空操作 | |
{ | |
StackNode<T> *p; | |
while(top!=NULL) | |
{ | |
p=top; | |
top=top->link; | |
delete p; | |
} | |
} |
# 3. 进栈操作

template<class T> | |
void LinkedStack<T>::Push(T x)// 进栈操作 | |
{ | |
// 将元素值 x 插入到链式栈的栈顶,即链头 | |
top=new StackNode<T>(x,top);// 创建新结点 | |
assert(top!=NULL);// 创建失败退出 | |
} |
# 4. 出栈操作

template<class T> | |
bool LinkedStack<T>::Pop(T &x)// 出栈操作 | |
{ | |
// 删除栈顶结点,返回被删栈顶元素的值 | |
if(IsEmpty()==true) | |
{ | |
return false;// 栈空返回 | |
} | |
StackNode<T> *p=top;// 暂存栈顶元素 | |
top=top->link;// 退栈顶指针 | |
x=p->data; | |
delete p;// 释放结点 | |
return true; | |
} |
进栈和出栈算法等等时间复杂度均为 O (1)
# 5. 取栈顶操作

template<class T> | |
bool LinkedStack<T>::getTop(T &x) const | |
{ | |
if(IsEmpty()==true) | |
{ | |
return false;// 栈空返回 | |
} | |
x=top->data; // 返回栈顶元素的值 | |
return true; | |
} |
# 三、双栈共享一个栈空间

# 1. 进栈操作
// 同一个数组 V [] 来同时存放两个栈 | |
//top0: 栈 0(左栈)的栈顶指针 | |
//top1: 栈 1(右栈)的栈顶指针 | |
bool push(DualStack &DS,Type x,int i)// 向双栈中的第 i 个栈压入元素 x | |
{ | |
if(DS.top0+1==DS.top1)// 栈满 | |
{ | |
return false; | |
} | |
if(i==0)// 若要向第 0 个栈压入元素 | |
{ | |
DS.top0++; // 栈顶指针右移一位 | |
DS.V[DS.top0]=x; // 新元素放入栈顶 | |
} | |
else// 向第 1 个栈压入元素 | |
{ | |
DS.top1--; // 栈顶指针左移一位 | |
DS.V[DS.top1]=x; // 新元素放入栈顶 | |
} | |
return true;// 压栈成功 | |
} |
# 2. 出栈操作
bool Pop(DualStack &DS,Type &x,int i)// 向双栈中的第 i 个栈弹出元素,赋值给 x | |
{ | |
if(i==0)// 左栈 | |
{ | |
if(DS.top0==-1)// 栈空 | |
{ | |
return false; | |
} | |
x=DS.V[DS.top0]; | |
DS.top0--; | |
} | |
else// 右栈 | |
{ | |
if(DS.top1==maxsize)// 栈空 | |
{ | |
return false; | |
} | |
x=DS.V[DS.top1]; | |
DS.top1++; | |
} | |
return true; | |
} |
# 四、顺序队列

# 1. 队列的抽象数据类型
template<class T> | |
class Queue | |
{ | |
public: | |
Queue(){} // 构造函数 | |
~Queue(){} // 析构函数 | |
virtual bool EnQueue(T x)=0; // 进队列 | |
virtual bool DeQueue(T &x)=0; // 出队列 | |
virtual bool getFront(T &x)=0; // 取队头 | |
virtual bool IsEmpty() const=0; // 判队列空 | |
virtual bool IsFull() const=0; // 判队列满 | |
}; |
# 2. 顺序队列的类定义

template<class T> | |
class SeqQueue// 队列类定义 | |
{ | |
protected: | |
int rear,front; // 队尾与队头指针 | |
T *elements; // 队列存放数组 | |
int maxSize; // 队列最大容量 | |
public: | |
SeqQueue(int sz=10); // 构造函数 | |
~SeqQueue() // 析构函数 | |
{ | |
delete []elements; | |
} | |
bool EnQueue(const T &x); // 新元素进队列 | |
bool DeQueue(T &x); // 退出队头元素 | |
bool getFront(T &x); // 取队头元素值 | |
void makeEmpty() | |
{ | |
front=rear=-1; | |
} | |
bool IsEmpty() const // 判队列空 | |
{ | |
return front==rear; | |
} | |
bool IsFull() const // 判队列满 | |
{ | |
return(rear==maxSize-1); | |
} | |
int getSize() const // 获取当前元素个数 | |
{ | |
return rear-front; | |
} | |
}; |
# 3. 入队操作

template<class T> | |
bool SeqQueue<T>::EnQueue(const T &x)// 入队操作 | |
{ | |
if(rear==maxSize-1) // 队列已满 | |
{ | |
cout <<"overflow"; | |
return false; | |
} | |
else | |
{ | |
rear++; // 队尾位置指示器后移一个位置 | |
elements[rear]=x; // 填入新元素 | |
return true; | |
} | |
} |
# 4. 出队操作

template<class T> | |
bool SeqQueue<T>::DeQueue(T &x)// 出队操作 | |
{ | |
if(front==rear) // 队列为空 | |
{ | |
cout <<"underflow"; | |
return false; | |
} | |
else | |
{ | |
front++; // 队头置位指示器后移一个位置 | |
x=elements[front]; // 暂存对头元素 | |
return true; // 出列成功 | |
} | |
} |
入队和出队算法是时间复杂度均为 O (1)
# 五、循环队列

# 1. 首尾结合的实现
# 方法一
// 用条件判断实现首尾结合 | |
if(r==maxSize-1)// 队尾指针到数组最后一个位置 | |
{ | |
r=0;// 回到数组开头(循环) | |
} | |
else | |
{ | |
r++;// 没到末尾,正常后移 | |
} |
# 方法二
// 把队头、队尾指示器对 maxSize 取模后 + 1 | |
// 注意:为了算法的方便,约定:初始时,队头、队尾指示器均指向最后一个单元位置, | |
// 即 front=rear=maxSize-1 或者初始化时 front=rear=0 | |
i=(i+1)%maxSize//i 可以是 front(队头)或 rear(队尾) |
# 2.” 空”“满” 问题的实现

# 入队操作
template<class T> | |
bool SeqQueue<T>::EnQueue(const T &x)// 入队操作 | |
{ | |
if((rear+1)%maxSize==front) // 判满 | |
{ | |
return false; | |
} | |
else | |
{ | |
rear=(rear+1)%maxSize; // 队尾指针后移一位 | |
elements[rear]=x; // 新元素存储队尾指针指向的位置 | |
return true; // 入队成功 | |
} | |
} |
# 出队操作

template<class T> | |
bool SeqQueue<T>::DeQueue(T &x)// 出队操作 | |
{ | |
if(rear==front)// 判空操作 | |
{ | |
return false; | |
} | |
else | |
{ | |
front=(front+1)%maxSize; // 队头指针后移一位 | |
x=elements[front]; // 新队头位置的元素赋值给引用参数 x | |
return true; // 出队成功 | |
} | |
} |
# 3. 判满操作
template<class T> | |
bool SeqQueue::IsFull() const // 判满操作 | |
{ | |
return ((rear+1)%maxSize==front); | |
} |
# 4. 计算元素个数
template<class T> | |
int SeqQueue::getSize() const // 计算元素个数 | |
{ | |
return (rear-front+maxSize)%maxSize; | |
} |
# 六、链式队列

# 1. 链式队列结点类定义
template<class T> | |
struct QueueNode // 队列结点类定义 | |
{ | |
public: | |
T data; // 队列结点数据 | |
QueueNode<T> *link; // 结点链指针 | |
QueueNode(T d=0,QueueNode<T> *next=NULL) : data(d),link(next){}// 构造函数 | |
}; |
# 2. 链式队列类定义
template<class T> | |
class LinkedQueue | |
{ | |
private: | |
QueueNode<T> *front,*rear; // 队头、队尾指针 | |
public: | |
LinkedQueue() : rear(NULL),front(NULL) {} // 构造函数 | |
~LinkedQueue(); // 析构函数 | |
bool EnQueue(const T &x); // 入队操作 | |
bool DeQueue(T &x); // 出队操作 | |
bool GetFront(T &x); | |
void MakeEmpty(); // 实现与~Queue () 同 | |
bool IsEmpty() const // 判空函数 | |
{ | |
return front==NULL; | |
} | |
}; |
# 3. 入队操作

template<class T> | |
bool LinkedQueue<T>::EnQueue(const T &x)// 入队操作 | |
{ | |
// 将新元素 x 插入到队列的队尾 | |
if(front==NULL)// 队列为空 | |
{ | |
front=rear=new QueueNode<T>(x);// 创建第一个结点 | |
if(front==NULL) // 分配失败 | |
{ | |
return false;// 分配失败 | |
} | |
} | |
else// 队列不空 | |
{ | |
rear->link=new QueueNode<T>(x);// 插入 | |
if(rear->link==NULL)// 分配失败 | |
{ | |
return false;// 分配失败 | |
} | |
rear=rear->link; | |
} | |
return true; | |
} |
# 4. 出队操作
template<class T> | |
bool LinkedQueue<T>::DeQueue(T &x)// 出队操作 | |
{ | |
// 如果队列不空,将队头结点从链式队列中删去 | |
if(IsEmpty()==true) // 判空 | |
{ | |
return false; | |
} | |
QueueNode<T> *p=front; | |
x=front->data; | |
front=front->link; | |
delete p; | |
return true; | |
} |
入队和出队算法的时间复杂度均为 O (1)
# 5. 取队头元素操作
template<class T> | |
bool LinkedQueue<T>::GetFront(T &x) // 取队头元素操作 | |
{ | |
// 若队列不空,则函数返回队头元素的值 | |
if(IsEmpty()==true) // 判空 | |
{ | |
return false; | |
} | |
x=front->data; | |
return true; | |
} |
# 6. 析构函数
template<class T> | |
LinkedQueue<T>::~LinkedQueue()// 析构函数 | |
{ | |
QueueNode<T> *p; | |
while(front!=NULL)// 不空 | |
{ | |
p=front; | |
front=front->link; | |
delete p; | |
} | |
} |