栈
先进后出, 后进现出
- 限定仅在表的一端进行插入和删除操作的线性表
操作
- 初始化
- 入栈
- 出栈
- 取值
- 判断栈满栈空
- 双栈共享
顺序栈
// 顺序栈类模板
template<class ElemType>
class SqStack
{
protected:
// 数据成员:
ElemType *elems; // 元素存储空间
int maxSize; // 栈最大元素个数
int count; // 元素个数
public:
// 抽象数据类型方法声明及重载编译系统默认方法声明:
SqStack(int size = DEFAULT_SIZE); // 构造函数模板
virtual ~SqStack(); // 析构函数模板
int Length() const; // 求栈长度
bool Empty() const; // 判断栈是否为空
void Clear(); // 将栈清空
void Traverse(void (*visit)(const ElemType &)) const; // 遍历栈
bool Push(const ElemType &e); // 入栈
bool Top(ElemType &e) const; // 返回栈顶元素
bool Pop(ElemType &e); // 出栈
bool Pop(); // 出栈
SqStack(const SqStack<ElemType> &source); // 复制构造函数模板
SqStack<ElemType> &operator =(const SqStack<ElemType> &source); // 重载赋值运算符
};
判断栈满:count = maxSize
判断栈空:count = 0
链式栈
表头作为栈顶好,入栈方便
// 链栈类模板
template<class ElemType>
class LinkStack
{
protected:
// 数据成员:
Node<ElemType> *top; // 栈顶指针
int count; // 元素个数
public:
// 抽象数据类型方法声明及重载编译系统默认方法声明:
LinkStack(); // 无参数的构造函数模板
virtual ~LinkStack(); // 析构函数模板
int Length() const; // 求栈长度
bool Empty() const; // 判断栈是否为空
void Clear(); // 将栈清空
void Traverse(void (*visit)(const ElemType &)) const ; // 遍历栈
bool Push(const ElemType &e); // 入栈
bool Top(ElemType &e) const; // 返回栈顶元素
bool Pop(ElemType &e); // 出栈
bool Pop(); // 出栈
LinkStack(const LinkStack<ElemType> &source); // 复制构造函数模板
LinkStack<ElemType> &operator =(const LinkStack<ElemType> &source); // 重载赋值运算符
};
入栈:
- 建立新的栈顶
- 新栈顶指针指向旧栈顶
- 栈顶指针赋值新栈顶
- 栈元素+1
出栈:
- 备份旧栈顶
- 栈顶指针赋值旧栈顶->next
- 删除旧栈顶
队列
仅在表的一端进行插入,在表的另一端删除
先进先出
队头:删除元素
队尾:插入元素
基本操作:
- 入队
- 出队
- 读取队头元素值
- 求队长
- 建队列
- 判断队满、队空
链队列
需要两个指针front
和 rear
指向队列队头和队尾
链表头作为队头、链表尾作为队尾好,便于入队出队
为方便加上头接点
入队:
- 旧队尾指向新队尾
- 队尾指针指向新队尾
出队:
- 备份旧队首;
- 队首指针赋值指旧队首
next
- 删除旧队首指针
循环队列(处理顺序链表队列)
顺序链表队列问题:假溢出问题
解决:
- 平移,发生假溢出将所有元素移到开头
- 使用动态数组,重新分配空间
- 使用环形数组
front = (front + 1)%MAXSIZE;
rear = (rear + 1) & MAXSIZE;
当到达顺序表尾时将数据加到开头
但是队列满和空的条件仍相同
解决:
- 标志位
- 计数器
- 少用一个空间,尾指针+1 = 头指针作为队列满的条件
应用
- 表达式求值
表达式包括:
- 操作数
- 常数
- 标识符
- 运算符
- 算数
- 逻辑
- 关系
- 界限符
- 括号
- 结束符
解法:
-
设定两栈:操作数或运算结果栈、运算符栈
-
操作符的优先级
-
序列检测