本文从栈的定义开始,根据栈的两种存储结构,顺序和链式,分别实现栈的基本操作。
栈的定义
栈——只允许通过访问它的一端来实现数据存储和检索的一种线性数据结构。即从固定一端插入数据、删除数据,后插入的先出,先插入的后出,因此,栈也称为(Last In First Out, LIFO)后进先出的线性表。栈中做插入和删除的一端作为栈顶(Top),另一端为栈底(Bottom)。
栈的基本操作
- 初始化栈 initStack():初始化栈顶指针和栈空间值
- 判断栈是否为空 isEmpty():判断当前栈空间是否为空,即 top == -1 是返回真,否返回假
- 判断栈空间是否已满 isFull():每个元素入栈前,都需要判断栈空间是否已满,若已满,则元素不入栈
- 入栈 Push():将元素加入栈顶,并且更新栈顶指针,入栈前需判断栈是否已满
- 出栈 Pop():将栈顶元素从栈中弹出,并且更新栈顶指针
- 读栈顶元素 getTopValue():读取栈顶元素的值
顺序栈实现
使用一固定大小的数组来实现栈的顺序存储,也叫顺序栈。栈空间的容量有限,当某个元素入栈时先要判断栈空间是否够用,如果栈满,则元素不能入栈,否则会导致栈溢出。下面程序模拟元素入栈、出栈、读栈等基本操作。
// 栈的C语言数组实现
#include <stdio.h>
#include <string.h>
#define MAXSIZE 10
typedef struct {
char data[MAXSIZE];
int top;
}Stack;
Stack St;
void initStack(Stack *S) {
S -> top = -1;
memset(S -> data, 0, MAXSIZE);
}
int isFull(Stack *S) {
return (S -> top == MAXSIZE - 1) ? 1 : 0;
}
int isEmpty(Stack *S) {
return (S -> top == -1) ? 1 : 0;
}
void Push(Stack *S, char ch) {
S -> top ++;
S -> data[S -> top] = ch;
printf("%d 号元素 %c 入栈!\n", S->top, ch);
}
void Pop(Stack *S) {
S -> top --;
}
char getTopValue(Stack *S) {
return S -> data[S -> top];
}
int main() {
char str[20] = {0};
printf("输入一组字符,按 Enter 键结束\n");
fgets(str, 20, stdin);
initStack(&St);
char *p = str;
while(*p != '\0') {
if(isFull(&St)) {
printf("栈空间已满!\n");
break;
}
else {
Push(&St, *p);
}
p++;
}
printf("########## 入栈结束 ##########\n");
while(!isEmpty(&St)) {
printf("%d 号元素 %c 出栈!\n", St.top, getTopValue(&St));
Pop(&St);
}
if(isEmpty(&St)) {
printf("当前栈为空 top = %d\n", St.top);
printf("########## 出栈结束 ##########\n");
}
return 0;
}
执行结果如下:该顺序栈最多存储10个字符,栈满则入栈结束
链式栈实现
使用链表实现栈的链式存储,也叫链栈。因为栈的元素的插入和删除仅在栈顶端进行,因此链表的头指针即作为栈顶指针。
以下栈的链表实现代码,模拟栈的入栈、出栈、读栈顶操作,栈的初始化由申请栈元素空间时完成,通过 pushFlag 标识符判断是否开始入栈,返回值 top 更新栈顶指针。
// 栈的C语言链表实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 20
typedef struct stack {
char data;
struct stack *next;
}Stack;
Stack *Push(Stack *top, char ch, int *pushFlag) {
if(*pushFlag == 0) {
top -> data = ch;
*pushFlag = 1;
}
else {
Stack *st = (Stack *)malloc(sizeof(Stack));
st -> data = ch;
st -> next = NULL;
st -> next = top;
top = st;
}
printf("元素 %c 已入栈!\n", top -> data);
return top;
}
Stack *Pop(Stack *top) {
Stack *tmp = top;
top = top -> next;
free(tmp);
tmp = NULL;
return top;
}
char getTopValue(Stack *top) {
return top -> data;
}
int main() {
Stack *top = (Stack *)malloc(sizeof(Stack));
top -> next = NULL;
char str[MAXSIZE] = {0};
int pushFlag = 0;
printf("输入一组字符,按 Enter 键结束\n");
fgets(str, MAXSIZE, stdin);
int i;
for(i = 0; str[i] != '\n'; i++) {
top = Push(top, str[i], &pushFlag);
}
printf("########## 入栈结束 ##########\n");
while(top != NULL) {
printf("栈顶元素: %c\n", getTopValue(top));
top = Pop(top);
}
printf("########## 出栈结束 ##########\n");
return 0;
}
程序执行过程如下: