目录
一、栈
栈(stack)是只允许在一端进行插入或删除操作的线性表,它是一种操作受限的线性表。
栈顶: 线性表允许进行插入删除的那一端。
栈底: 不允许进行插入和删除的那一端。
空栈: 不含有任何元素的空表。
栈的基本操作:
- InitStack(Stack &s): 初始化栈
- StackEmpty(Stack s): 判断一个栈是否为空
- Push(Stack &s, ElemType x): 入栈
- Pop(Stack &s, ElemType &x): 出栈
- GetTop(Stack s, ElemType &x): 获取栈顶元素
- DestroyStack(Stack &s): 销毁栈
- PrintStack(Stack s): 遍历栈
基于以上七种操作,我将从栈的不同存储结构出发,实现这些基本操作。
二、实现栈
1. 顺序栈
#include <stdio.h>
#define MAX_SIZE 10
typedef int ElemType;
// 顺序栈
typedef struct {
ElemType data[MAX_SIZE];
int top; // 指向可插入的位置
} SqStack;
// 初始化栈
void InitStack(SqStack &s) {
s.top = 0;
}
// 栈空判断
bool StackEmpty(SqStack &s) {
return s.top == 0 ? true : false;
}
// 入栈
bool push(SqStack &s, ElemType x) {
if (s.top == MAX_SIZE) {
printf("栈已满,不能继续添加元素啦!\n");
return false;
}
s.data[s.top++] = x;
return true;
}
// 出栈
bool pop(SqStack &s) {
if (StackEmpty(s)) {
printf("很抱歉,此时栈为空。\n");
return false;
}
s.data[s.top--] = 0;
return true;
}
// 取栈顶元素
ElemType GetTop(SqStack s) {
return s.data[s.top - 1];
}
// 销毁栈,逻辑上销毁
void DestroyStack(SqStack &s) {
s.top = 0;
}
// 打印顺序栈
void PrintStack(SqStack s) {
if (StackEmpty(s)) {
return;
}
int i = s.top - 1;
while (i >= 0) {
printf("%d ", s.data[i]);
i--;
}
printf("\n");
}
int main() {
SqStack s;
InitStack(s);
push(s, 1);
push(s, 2);
push(s, 3);
pop(s);
push(s, 4);
ElemType x = GetTop(s);
printf("栈顶元素为:%d\n", x);
PrintStack(s);
pop(s);
pop(s);
PrintStack(s);
DestroyStack(s);
PrintStack(s);
}
顺序栈使用一段连续空间来存储栈,通过设置top指针指向栈顶元素或可插入元素的位置,来表示栈结构。
2. 链栈
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
// 链栈
typedef struct LinkNode {
ElemType data;
LinkNode *next;
} LiStack;
// 初始化栈
void InitStack(LiStack &s) {
s.next = NULL;
}
// 判断栈空
bool StackEmpty(LiStack s) {
return s.next == NULL ? true : false;
}
// 入栈
void Push(LiStack &s, ElemType e) {
LinkNode *p = (LinkNode *) malloc(sizeof(LinkNode));
p->data = e;
p->next = s.next;
s.next = p;
printf("进栈元素是%d\n", e);
}
// 取栈顶元素
ElemType GetTop(LiStack s) {
return s.next->data;
}
// 出栈
ElemType Pop(LiStack &s) {
if (StackEmpty(s)) {
return -1;
}
LinkNode *p = s.next;
ElemType data = GetTop(s);
s.next = p->next;
free(p);
printf("出栈元素是%d\n", data);
return data;
}
// 打印链栈中的全部元素
void PrintStack(LiStack s) {
if (StackEmpty(s)) {
printf("当前栈为空!\n");
return;
}
LinkNode *p = s.next;
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
void DestroyStack(LiStack &s) {
LinkNode *q, *p = s.next;
while (p != NULL) {
q = p;
p = p->next;
free(q);
}
s.next = NULL; // 将链栈的头指针置为 NULL
printf("成功销毁链栈!\n");
}
int main() {
LiStack s;
InitStack(s);
Push(s, 10);
Push(s, 5);
Push(s, 1);
Push(s, 20);
PrintStack(s);
ElemType e = GetTop(s);
printf("栈顶元素为%d\n", e);
Pop(s);
Pop(s);
PrintStack(s);
DestroyStack(s);
PrintStack(s);
}
链栈通过一组任意的存储单元来栈中的元素,但链栈是操作受限的线性表,它只允许从表头进栈,通过头插法可以实现。
3. 共享栈
#include <stdio.h>
#define MAX_SIZE 10
typedef int ElemType;
// 共享栈
typedef struct {
ElemType data[MAX_SIZE];
int top; // 指向栈顶 0号栈
int base; // 指向栈底 1号栈
} ShareStack;
// 初始化共享栈
void InitStack(ShareStack &s) {
s.base = -1;
s.top = MAX_SIZE;
}
// 判断共享栈为空
bool StackEmpty(ShareStack s) {
return (s.base == -1 && s.top == MAX_SIZE) ? true : false;
}
// 判断共享栈是否已满
bool StackFull(ShareStack s) {
return (s.top - s.base == 1) ? true : false;
}
// 入栈
bool Push(int type, ShareStack &s, ElemType e) {
if (StackFull(s)) {
printf("当前栈已满!\n");
return false;
}
if (type == 1) {
// 表示1号栈,栈底
s.data[++s.base] = e;
}
if (type == 0) {
// 表示0号栈,栈顶
s.data[--s.top] = e;
}
return true;
}
ElemType GetTop(int type, ShareStack s) {
ElemType data;
if (type == 1) {
data = s.data[s.base];
}
if (type == 0) {
data = s.data[s.top];
}
return data;
}
// 出栈
ElemType Pop(int type, ShareStack &s) {
if (StackEmpty(s)) {
printf("当前栈为空,没有可以出栈的元素!\n");
return NULL;
}
ElemType e = GetTop(type, s);
if (type == 1) {
--s.base;
}
if (type == 0) {
++s.top;
}
printf("出栈元素是%d\n", e);
return e;
}
// 打印栈元素
void PrintStack(int type, ShareStack s) {
if (type == 1) {
printf("1号栈的元素有:");
int index = s.base;
while (index >= 0) {
printf("%d ", s.data[index--]);
}
printf("\n");
}
if (type == 0) {
printf("0号栈的元素有:");
int index = s.top;
while (index < MAX_SIZE) {
printf("%d ", s.data[index++]);
}
printf("\n");
}
}
// 销毁共享栈
void DestroyShareStack(ShareStack &s) {
s.top = MAX_SIZE;
s.base = -1;
}
int main() {
ShareStack s;
InitStack(s);
Push(1, s, 5);
Push(1, s, 5);
Push(1, s, 1);
Push(1, s, 3);
Push(1, s, 10);
Push(0, s, -10);
Push(0, s, -5);
Push(0, s, 0);
Push(0, s, -1);
Push(1, s, 100);
Push(0, s, 2);
PrintStack(1, s);
PrintStack(0, s);
Pop(0, s);
Pop(1, s);
Pop(0, s);
PrintStack(1, s);
PrintStack(0, s);
DestroyShareStack(s);
}
共享栈是指同一片连续空间,分别从相对方向存放各个栈的元素,它节省了所需的空间,不同于顺序栈的是,在判断栈满时,是通过判断两个栈顶指针对应的索引关系。
栈的数据结构本质上和线性表是相同的,在陈述内容时,更多的是不同存储结构下的栈的基本操作的实现。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章!