栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(LastIn First Out)的线性表,简称LIFO结构。
理解栈的定义需要注意:
首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底。
关于链式栈和顺式栈比较
它们在时间复杂度上是一样的,均为O(1)。对于空间性能,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费的问题,但它的优势是存取时定位很方便,而链栈则要求每个元素都有指针域,这同时也增加了一些内存开销,但对于栈的长度无限制。所以它们的区别和线性表中讨论的一样,如果栈的使用过程中元素变化不可预料,有时很小,有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。
栈有什么应用?
系统借助栈的结构来实现递归。
递归函数前行阶段,对于每一层递归,函数的局部变量、参数值以及返回地址都被压入栈中。在退回阶段,位于栈顶的局部变量、参数值和返回地址被弹出,用于返回调用层次中执行代码的其余部分,也就是恢复了调用的状态。
由后缀表达式得到表达式树
我们一次一个符号地读人表达式。如果符号是操作数,那么我们就建立一个单节点树并将一个指向它的指针推人栈中。如果符号是操作符,那么我们就从栈中弹出指向两棵树 T 和 T 的那两个觜针( T 的先弹出)并形成一棵新的树,该树的根就是操作符,它的左、右儿子分别指向 T :和 T 。然后将指向这棵新树的指针压人栈中。这样就能得到后缀表达式对应的表达式树。
中缀表达式转后缀表达式
栈的数据结构和基本操作的定义:(用C描述)(链式)
具体完整代码:
stack.h
#pragma once
#ifndef STACK_H
#include<stdio.h>
#include<stdlib.h>
struct node;
typedef struct node* PtrToNode;
typedef struct node* Stack; //栈
Stack createStack(); //创建一个栈
void disposeStack(Stack stack); //销毁栈
void makeStackEmpty(Stack stack); //清空栈
bool IsEmpty(Stack stack); //判断是否为空栈
void Pop(Stack stack); //出栈
void Push(Stack stack, int value); //入栈
int TopValue(Stack stack); //取栈顶元素
PtrToNode Top(Stack stack); //取栈顶
void printStack(Stack stack); //从栈打印栈
#endif
stack.c
#include<stdio.h>
#include<stdlib.h>
#include"Stack.h"
typedef struct node {
int value;
PtrToNode next;
}Node;
//创建栈
Stack createStack()
{
Stack stack = (Stack)malloc(sizeof(Node));
stack->next = NULL;
return Stack();
}
//销毁栈
void disposeStack(Stack stack) {
makeStackEmpty(stack);
free(stack);
}
//清空栈
void makeStackEmpty(Stack stack) {
if (!IsEmpty(stack)) {
Pop(stack);
makeStackEmpty(stack);
}
}
//判断是否为空栈
bool IsEmpty(Stack stack) {
return stack->next == NULL;
}
//出栈
void Pop(Stack stack) {
if (!IsEmpty(stack)) {
PtrToNode out = stack->next;
stack->next = out->next;
free(out);
}
}
//入栈
void Push(Stack stack, int value) {
PtrToNode node = (PtrToNode)malloc(sizeof(Node));
node->value = value;
if (stack->next == NULL) {
stack->next = node;
node->next = NULL;
}
else {
node->next = stack->next->next;
stack->next = node;
}
}
//取栈顶元素
int TopValue(Stack stack) {
if (!IsEmpty(stack)) {
return stack->next->value;
}
else
return 0;
}
//取栈顶
PtrToNode Top(Stack stack) {
if (!IsEmpty(stack)) {
return stack->next;
}
else
return NULL;
}
//
void printStack(Stack stack) {
if (!IsEmpty(stack)) {
PtrToNode move = stack->next;
while (move != NULL) {
printf("%d", move->value);
move = move->next;
}
}
}