1. 基本特征
具有后进先出特征的数据结构叫做 堆栈 LIFO(last in first out)
× 堆栈是只能在一端进行增删元素的数据结构,该位置称为栈顶,一般用下标top表示
2 基本操作
创建(create)、销毁(destroy)、入栈(push)、出栈(pop)、遍历(travel)、判断栈是否为满(full)、
判断栈是否为空(empty)、计算栈中元素的个数(size)、 查看栈顶元素值(peek)
具有后进先出特征的数据结构叫做 堆栈 LIFO(last in first out)
× 堆栈是只能在一端进行增删元素的数据结构,该位置称为栈顶,一般用下标top表示
2 基本操作
创建(create)、销毁(destroy)、入栈(push)、出栈(pop)、遍历(travel)、判断栈是否为满(full)、
判断栈是否为空(empty)、计算栈中元素的个数(size)、 查看栈顶元素值(peek)
下面基于物理存储结构的两种形式实现堆栈功能
基于顺序存储结构的堆栈实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 定义堆栈的数据类型
typedef struct
{
int *arr; //存储空间的首地址
int len; //存储空间的大小
int top; //下标,记录栈顶的位置
} Stack;
//实现堆栈创建的功能
Stack *creat(int len);
//实现堆栈销毁的功能
void destroy(Stack *ps);
//判断栈是否为满
bool full(Stack *ps);
//判断栈是否为空
bool empty(Stack *ps);
//实现入栈的操作
void push(Stack *ps, int data);
//遍历栈中所有元素的操作
void travel(Stack *ps);
//实现出栈的基本操作
int pop(Stack *ps);
//实现计算栈中元素个数
int size(Stack *ps);
//实现查看栈顶元素值
int peek(Stack *ps);
int main(void)
{
//创建堆栈变量
Stack *ps = creat(5);
printf("%s\n", full(ps)? "栈满了": "栈没有满");
printf("%s\n", empty(ps)? "栈空了": "栈没有空");
printf("---------------------------\n");
int i = 0;
for (i =1; i <7; i++)
{
push(ps, i*10+i);
}
travel(ps); // 11 22 33 44 55
printf("----------------------------\n");
printf("出栈的元素值是:%d\n", pop(ps)); // 55
travel(ps); // 11 22 33 44
printf("出栈的元素是:%d\n", pop(ps)); // 44
travel(ps); // 11 22 33
printf("栈顶元素是:%d\n", peek(ps)); // 33
travel(ps); // 11 22 33
printf("栈中元素的个数是:%d\n", size(ps));//3
//销毁堆栈变量
destroy(ps);
return 0;
}
//实现出栈的基本操作
int pop(Stack *ps)
{
if (empty(ps))
{
printf("栈已经空,出栈失败\n");
return -1; //表示出错
}
return ps->arr[--(ps->top)];
}
//计算栈中元素个数
int size(Stack *ps)
{
return ps->top;
}
//查看栈顶元素值
int peek(Stack *ps)
{
if (empty(ps))
{
printf("栈空了,查看栈顶元素失败\n");
return -1; //表示失败
}
return ps->arr[ps->top - 1];
}
//遍历栈中所有元素的操作
void travel(Stack *ps)
{
int i = 0;
printf("栈中的元素有:\n");
for (i =0; i <ps->top; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
//实现入栈的操作
void push(Stack *ps, int data)
{
if (full(ps))
{
printf("栈满了,入栈失败\n");
return;
}
//ps->arr[ps->top] = data;
//ps->top++;
ps->arr[ps->top++] = data;
}
//判断是否为满
bool full(Stack *ps)
{
return ps->len == ps->top;
}
//判断栈是否为空
bool empty(Stack *ps)
{
return 0 == ps->top;
}
//实现堆栈销毁的功能
void destroy(Stack *ps)
{
free(ps->arr);
free(ps);
ps->arr = NULL;
ps = NULL;
}
//实现堆栈创建的功能
Stack *creat(int len)
{
//1.创建堆栈,进行初始化
// Stack stack; 局部变量,生命周期短暂
// 动态申请的内存生命周期比较长
Stack *ps = (Stack *)malloc(sizeof(Stack));
ps->arr = (int *)malloc(sizeof(int) * len);
ps->len = len;
ps->top = 0;
//2.返回堆栈的首地址
return ps;
}
基于链式存储结构的堆栈实现
#include <stdio.h>
#include <stdlib.h>
//定义节点的数据类型
typedef struct Node
{
int data; //数据内容
struct Node *next; //记录下一个节点地址
} Node;
//定义栈的数据类型
typedef struct
{
Node *head; //头指针
} Stack;
//判断栈是否为空
int empty(Stack *ps);
//判断栈是否为满
int full(Stack *ps);
//实现入栈操作
void push(Stack *ps, int data);
//实现遍历操作
void travel(Stack *ps);
//查看栈顶元素
int peek(Stack *ps);
//计算栈中元素的个数
int size(Stack *ps);
//实现出栈操作
int pop(Stack *ps);
//清空栈中所有元素
void clear(Stack *ps);
int main(void)
{
//定义栈并且进行初始化
Stack stack;
stack.head = NULL;
push(&stack, 11); // 11
travel(&stack);
push(&stack, 22); // 22 11
travel(&stack);
push(&stack, 33); // 33 22 11
travel(&stack);
printf("%s\n", empty(&stack)?"栈空了":"栈没有空");
printf("%s\n", full(&stack)?"栈满了":"栈没有满");
printf("获取到的栈顶元素是:%d\n", peek(&stack));// 33
printf("栈中元素的个数是:%d\n", size(&stack)); // 3
printf("--------------------------\n");
travel(&stack); //33 22 11
printf("出栈的元素是:%d\n", pop(&stack));//33
travel(&stack); //22 11
//清空栈中所有元素
clear(&stack);
travel(&stack); //什么也没有
return 0;
}
//清空栈中所有元素
void clear(Stack *ps)
{
while (ps->head != NULL)
{
//使用临时指针记录第一个节点
Node *p = ps->head;
//头指针指向下一个节点
ps->head = ps->head->next;
//释放p指向的节点
free(p);
p = NULL;
}
}
//实现出栈操作
int pop(Stack *ps)
{
if (empty(ps))
{
return -1; //出栈失败
}
//准备一个指针记录要删除的节点地址
Node *p = ps->head;
//头指针指向下一个节点
ps->head = ps->head->next;
//单独存储要删除的节点元素值
int tmp = p->data;
//释放要删除的节点内存
free(p);
p = NULL;
//返回已经释放的节点元素值
return tmp;
}
//查看栈顶元素
int peek(Stack *ps)
{
if (empty(ps))
{
return -1; // 获取失败
}
return ps->head->data;
}
//计算栈中元素的个数
int size(Stack *ps)
{
int cnt = 0;
Node *p = ps->head;
while(p != NULL)
{
cnt++;
p = p->next;
}
return cnt;
}
//实现遍历操作
void travel(Stack *ps)
{
//给头指针寻找替身
Node *p = ps->head;
printf("栈中的元素有:");
while (p != NULL)
{
printf("%d ", p->data);
//指向下一个节点
p = p->next;
}
printf("\n");
}
//判断栈是否为空
int empty(Stack *ps)
{
return NULL == ps->head;
}
//判断栈是否为满
int full(Stack *ps)
{
return 0; //链式可以无限连接,没有满
}
//实现入栈操作
void push(Stack *ps, int data)
{
//1.创建新节点并初始化
//Node node; 局部变量 生命周期短
Node *pn = (Node *)malloc(sizeof(Node));
pn->data = data;
pn->next = NULL;
//2.插入新节点到头节点的位置
pn->next = ps->head; //新节点连接原头节点
ps->head = pn; //新节点成为头节点
}