3.3.1 栈模型
栈(stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫栈顶(top)。对栈的基本操作有Push(进栈)和Pop(出栈),前者相当于插入,后者则是删除最后插入的元素。最后插入的元素可以通过使用Top例程在执行Pop之前进行检查。对空栈进行的Pop或Top一般被认为是栈ADT的错误。另一方面,当运行Push时空间用尽是一个实现错误,但不是ADT错误。
栈有时又叫做LIFO(Last in first out)(后进先出)表。


图3-38表示在进行若干操作后的一个抽象的栈。一般的模型是,存在某个元素位于栈顶,而该元素是唯一的可见元素。
栈的链表实现
栈的第一种实现方法是使用单链表。我们通过在表前端插入来实现Push,通过删除表前端元素实现Pop。Top操作只是检测表前端元素并返回它的值。有时Pop操作和Top操作合二为一。缺点是对malloc和free的调用开销太大。
//stack.h
#ifndef STACK_H_
#define STACK_H_
typedef struct
{
char str[10];
int numb;
}Item;
typedef struct node
{
Item item;
struct node* next;
} Node;
typedef struct
{
Node* head;
}Stack;
/* 初始化栈 */
void STACKinit(Stack* pq);
/* 在头部添加栈 */
bool PushStack(Item a, Stack* pq);
/* 在头部推出栈 */
void PopStack(Stack* pq);
/* 遍历栈,输出栈的项*/
void Output(const Stack* pq);
#endif
//stack.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"STACK.h"
void STACKinit(Stack* pq)
{
pq->head = NULL;
}
bool PushStack(Item a, Stack* pq)
{
Node* New;
Node* pp = pq->head;
New = (Node*)malloc(sizeof(Node));
if (New == NULL)
{
printf("没分配内存\n");
return false;
}
New->item = a;
if (a.numb == 0) //判断是否为第一项,是的话New->next = NULL;
{
pq->head = New;
New->next = NULL;
}
else
{
New->next = pq->head;
pq->head = New;
}
return true;
}
void PopStack(Stack* pq)
{
Node* old;
old = pq->head;
pq->head = pq->head->next;
free(old);
}
void Output(const Stack* pq)
{
if (pq->head == NULL)
{
printf("空栈!\n");
return;
}
Node* pp = pq->head;
printf("栈中的项:\n");
while (pp != NULL)
{
printf("%s\n", pp->item.str);
pp = pp->next;
}
printf("项数:%d\n", pq->head->item.numb);
}
//main.c
#include<stdio.h>
#include<string.h>
#include"STACK.h"
int main(void)
{
Stack stack;
Item strn;
int i = 0;
STACKinit(&stack);
printf("输入0,退出 | 输入*:推出栈 | 输入l,查看栈\n");
while (1)
{
strn.numb = i;
scanf_s("%s", strn.str, 9);
if (strcmp(strn.str, "0") == 0)
{
break;
}
else if (strcmp(strn.str, "l") == 0)
{
strn.numb = i;
Output(&stack);
continue;
}
if (strcmp(strn.str, "*") != 0)
{
i++;
strn.numb = i;
PushStack(strn, &stack);
printf("推入成功!\n);
}
else
{
i--;
PopStack(&stack);
printf("推出成功!\n);
}
}
puts("Bye!");
return 0;
}
栈的数组实现
需要提前声明数组的大小。
//stack.h
#ifndef _STACK_H
#define _STACK_H
#define N 10
typedef int data_type;
//顺序栈
typedef struct stack
{
data_type arr[N]; //顺序连续大小固定
int top; //top ==-1;空.top == N-1;满 top 表示栈顶的位置
}Stack;
enum op
{
FULL = -3,
EMPTY,
NOEXIT,
OK
};
//创建栈
//返回值:Stack * 顺序存储的首地址
S