1.栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶
我们可以把栈想象成手枪子弹弹夹,一颗颗按进去后,先打出来的绝对是最后放进去的那一颗子弹,按子弹和出子弹都是在弹夹口操作。
栈一般用于括号匹配问题,力扣牛客上都有练习题。
如图:栈其实就是个只能在某一端操作的数组线性表
元素1入栈 此时栈顶元素为1
栈顶元素1出栈,此时元素7为栈顶元素
2.栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小,而链表必须要先找到最后一个节点才可以尾插。
可以使用静态数组也可以使用动态数组来实现,但静态的一般不实用,故使用动态数组实现
头文件
1.动态栈的结构
2.栈的基本功能的定义
#pragma once
#include <stdio.h>
#include<malloc.h>
typedef int STDataType;
//支持动态生长的栈结构
typedef struct Stack
{
STDataType* array;//数组
STDataType size;//有效元素个数
STDataType capacity;//容量
}Stack;
void CheckCapacity(Stack* ps); //容量检测
void StackInit(Stack* ps);//初始化栈
void StackPush(Stack* ps, STDataType x);//入栈
void StackPop(Stack* ps);//出栈
STDataType StackTop(Stack* ps);//获取栈顶元素
int StackEmpty(Stack* ps);//判断栈是否为空
int StackSize(Stack* ps);//求栈的有效元素
void StackDestory(Stack* ps);//栈的销毁
具体的函数定义实现
常见的问题详见注释
#include "stack.h"
#define DEFSTACKSIZE 50 //先初始为50字节的容量
//容量检测
void CheckCapacity(Stack* ps)
{
if (ps->size >= ps->capacity)//判断是否扩容
{
ps->capacity *= 2; //2倍扩容
ps->array = (STDataType *)realloc(ps->array, ps->capacity * sizeof(STDataType)); //ralloc:在array后继续申请空间
}
}
void StackInit(Stack* ps)//初始化
{
ps->array = (STDataType *)calloc(DEFSTACKSIZE, sizeof(STDataType));//calloc:申请数组空间并初始化为0
ps->capacity = DEFSTACKSIZE;
ps->size = 0;
}
void StackPush(Stack* ps, STDataType x) //数组尾部添加数据 即数组尾插入栈
{
CheckCapacity(ps);
ps->array[ps->size] = x;
ps->size++;
}
void StackPop(Stack* ps)//出栈
{
if (ps->size == 0)
{
return;
}
ps->size--;
}
STDataType StackTop(Stack* ps)//获取栈顶元素
{
if (ps->size == 0)//栈为空时即没有任何元素
{
return (STDataType)0;
}
return ps->array[ps->size - 1];//有元素时,返回栈顶元素
}
int StackEmpty(Stack* ps)//栈判空
{
return ps->size == 0;
}
int StackSize(Stack* ps)//获取里有效元素个数
{
return ps->size;
}
void StackDestory(Stack* ps)//栈的销毁
{
if (ps->array)
{
free(ps->array);//一定要释放申请的内存
ps->array = NULL;//且要置空,否则时悬空指针 即释放了内存,但是还是指向的之前指向的那个地址
ps->size = 0;
ps->capacity = 0;
}
}
对写出的功能的简单测试
#include "stack.h"
int main()
{
Stack ps;
StackInit(&ps);
StackPush(&ps, 1);
StackPush(&ps, 2);
StackPush(&ps, 3);
StackPush(&ps, 4);//1 2 3 4依次入栈
printf("%d\n",StackTop(&ps));//栈顶元素 4
StackPop(&ps); //4出栈
printf("%d\n", StackTop(&ps));//3为栈顶
StackPop(&ps);//3出栈
printf("%d\n", StackTop(&ps));//2为栈顶
StackPop(&ps);//2出栈
return 0;
}
3.总结
反正就是要多练,熟悉数组之后,再熟悉栈的规则之后就能理清关系了,不会了就多练,总会会的,,,,,,,,