线性结构——栈
堆栈
- 前缀、中缀和后缀表达式
- 表达式求值的基本方法
从左到右读入表达式的各项,运算数:入栈。运算符:从栈中弹出适当数量的运算数,计算并结果入栈,最后,堆栈顶上的元素就是表达式的结果值。
- 基本策略:将中缀表达式转化为后缀表达式
//例1:
2+9/3-5 ————> 2 9 3 5 / + -
// 运算数的相对顺序不变
// 运算符号顺序发生改变
需要存储等待中运算符号
要与当前的运算符与等待中的预算符号比较
//例2:
a * (b + c) / d ———— a b c + * d /
- 中例转换示例:
( 2*(9+6/3-5)+4)
栈的顺序存储实现
- 栈的顺序存储结构通常是由一个一维数组和一个记录栈顶元素位置的变量组成
typedef int Position;
typedef int ElementType;
struct SNode {
ElementType *Data; // 存储元素的数组
Position Top; // 栈顶指针
int MaxSize; // 栈顶的最大容量
};
typedef SNode* Stack;
#define ERROR -1
// 创建一个栈
Stack Create(int MaxSize)
{
Stack s = (Stack)malloc(sizeof(struct SNode));
s->Data = (ElementType*)malloc(sizeof(ElementType));
s->Top = -1;
s->MaxSize = MaxSize;
return s;
}
// 判断站是否满
bool Isfull(Stack S)
{
return S->Top = S->MaxSize - 1;
}
// 入栈
bool Push(Stack S, ElementType X)
{
if (Isfull(S))
{
std::cout << "栈已满,操作失败\n" << std::endl;
return false;
}
else
{
// 栈顶加 1
return S->Data[++(S->Top)] = X;
}
}
// 站是否为空
bool IsEmpty(Stack S)
{
// 注意双等号
return (S->Top == -1);
}
ElementType PopStack(Stack S)
{
if (IsEmpty(S))
{
std::cout << "栈已空,操作失败\n" << std::endl;
}
else
{
return (S->Data[(S->Top)--]);
}
}
栈的链式存储实现
- 栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的栈顶进行
typedef int ElementType;
typedef struct SNode* ptrToStack;
struct SNode {
ElementType Data; // 存储栈中元素
ptrToStack Next; // 栈顶指针
};
typedef ptrToStack Stack;
#define ERROR -1
// 创建一个栈
Stack Create( )
{
Stack s = (Stack)malloc(sizeof(struct SNode));
s->Next = NULL;
return s;
}
// 站是否为空
bool IsEmpty(Stack S)
{
// 注意双等号
return (S->Next == NULL);
}
// 入栈
bool Push(Stack S, ElementType X)
{
// 将元素压入堆栈 S
ptrToStack temCell = NULL;
temCell = (ptrToStack)malloc(sizeof(struct SNode));
temCell->Data = X;
temCell->Next = S->Next;
S->Next = temCell;
return true;
}
// 弹出数据
ElementType PopStack(Stack S)
{
ptrToStack firstCell;
ElementType topElem;
if (IsEmpty(S))
{
printf("堆栈空\n");
return ERROR;
}
else
{
firstCell = S->Next;
topElem = firstCell->Data;
S->Next = firstCell->Next;
free(firstCell);
return topElem;
}
}
堆栈的其他应用
- 函数调用及递归实现
- 深度优先搜索
- 回溯算法