一.栈模型
栈(Stack)又称后进先出表(LIFO List),是插入/删除操作被限制为只能在1个位置上进行的表.这个位置是表的末端,称为栈顶(Top).对栈的基本操作包括进栈(Push;在栈顶插入1个元素)和出栈(Pop;删除栈顶处的元素)
二.栈的实现
1.单链表实现:
在单链表实现下,所有操作均花费常数时间.这种实现的缺点在于malloc()和free()的开销是昂贵的,尤其是与指针相比
#include <stdio.h>
#include <malloc.h>
typedef int ElementType;
struct Node;
typedef struct Node* PtrToNode;
typedef PtrToNode Stack;
int IsEmpty(Stack S);
Stack CreateStack(void);
void MakeEmpty(Stack S);
void Push(ElementType X, Stack S);
ElementType Top(Stack S);
void Pop(Stack S);
struct Node {
ElementType Element;
PtrToNode Next;
};
int main(void) {
Stack S = CreateStack();
Push(10,S);
printf("%d\n",(S->Next->Element));//结果:10
printf("%d\n",Top(S));//结果:10
printf("%d\n",S->Next);//结果:11212160
Pop(S);
printf("%d\n",S->Next);//结果:0
}
int IsEmpty(Stack S) {//判断是否为空栈
return S->Next == NULL;
}
Stack CreateStack(void) {//创建栈
Stack S;
S = malloc(sizeof(struct Node));
if (S == NULL) {
printf("Out of Space");//应该报错
}
S->Next==NULL;
MakeEmpty(S);
return S;//注意:S本身不储存元素,S->Next才是栈顶
}
void MakeEmpty(Stack S) {//清空栈
if (S == NULL) {
printf("Must Create Stack First");//应该报错
} else {
while (!IsEmpty(S)) {
Pop(S);
}
}
}
void Push(ElementType X, Stack S) {//进栈
PtrToNode TmpCell;
TmpCell = malloc(sizeof(struct Node));
if (TmpCell == NULL) {
printf("Out of Memory");//应该报错
} else {
TmpCell->Element = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
}
}
ElementType Top(Stack S) {//返回栈顶元素
if (!IsEmpty(S)) {
return S->Next->Element;
}
printf("Empty Stack");
return 0;
}
void Pop(Stack S) {//出栈
PtrToNode FirstCell;
if (IsEmpty(S)) {
printf("Empty Stack");
} else {
FirstCell = S->Next;
S->Next = S->Next->Next;
free(FirstCell);
}
}
2.数组实现:
这种实现的缺点是需要事先声明数组的大小,因而会浪费一部分内存空间.这通常不是大问题,因为在典型的程序中,在任意时刻栈中元素的个数都不会太
多,数组通常也就不需要很大.如果不能保证这1点,那么使用单链表实现就更合适.在数组实现下,所有操作均花费常数时间,甚至可能直接对应某条机器
指令,这体现了栈在计算机科学中有多么基本.错误检测十分影响栈的执行效率,所以有时会略去而使用其他方法来保证不越界,但通常还是会保留
#include <stdio.h>
#include <malloc.h>
typedef int ElementType;
struct StackRecord;
typedef struct StackRecord* Stack;
int IsEmpty(Stack S);
int IsFull(Stack S);
Stack CreateStack(int MaxElements);
void DisposeStack(Stack S);
void MakeEmpty(Stack S);
void Push(ElementType X, Stack S);
ElementType Top(Stack S);
void Pop(Stack S);
ElementType TopAndPop(Stack S);
#define EmptyTOS (-1)
#define MinStackSize (5)
struct StackRecord {
int Capacity;//容量
int TopOfStack;//栈顶元素位置
ElementType * Array;//储存元素
};
int main(void) {
Stack S=CreateStack(10);
Push(1,S);
printf("%d\n",S->Array[S->TopOfStack]);//结果:1
}
int IsEmpty(Stack S) {//判断是否为空栈
return S->TopOfStack == EmptyTOS;
}
int IsFull(Stack S) {//判断栈是否已满
return S->TopOfStack == S->Capacity;
}
Stack CreateStack(int MaxElements) {//创建栈
Stack S;
if (MaxElements < MinStackSize) {
printf("Stack Size if Too Small");//应该报错
} else {
S = malloc(sizeof(struct StackRecord));
if (S == NULL) {
printf("Out of Space");//应该报错
} else {
S->Array = malloc(sizeof(ElementType) * MaxElements);
if (S == NULL) {
printf("Out of Space");//应该报错
} else {
S->Capacity = MaxElements;
}
}
}
MakeEmpty(S);
return S;
}
void DisposeStack(Stack S) {//释放栈
if (S != NULL) {
free(S->Array);
free(S);
}
}
void MakeEmpty(Stack S) {//清空栈
S->TopOfStack = EmptyTOS;
}
void Push(ElementType X, Stack S) {//进栈
if (IsFull(S)) {
printf("Full Stack");//应该报错
} else {
S->Array[++S->TopOfStack] = X;
}
}
ElementType Top(Stack S) {//返回栈顶元素
if (!IsEmpty(S)) {
return S->Array[S->TopOfStack];
}
printf("Empty Stack");
return 0;
}
void Pop(Stack S) {//出栈
if (IsEmpty(S)) {
printf("Empty Stack");
}
else {
S->TopOfStack--;
}
}
ElementType TopAndPop(Stack S) {//返回栈顶元素并出栈
if (!IsEmpty(S)) {
return S->Array[S->TopOfStack--];
}
printf("Empty Stack");
return 0;
}
三.应用
1.平衡符号:
2.后缀表达式:
3.中缀到后缀的转换: