1.栈的基本概念
1.1栈的定义
栈是一种线性表,只能在一端进行数据的插入或删除,可以用数组或链表来实现,这里以数组为例进行说明
栈顶 :数据出入的那一端,通常用Top表示
栈底 :相对于栈顶的另一端,也是固定的一端,不允许数据的插入和删除
空栈:不含数据的栈
1.2栈的基本操作
栈的初始化:通常用STInit(&St)表示,用来初始化一个栈St
入栈:一般用STPush(&St, x)表示,给栈St插入数据x,也叫做进栈,压栈,同时要注意是否栈满,栈满则需要扩容
出栈:一般用STPop(&St)表示,给栈St删除数据,有时也叫弹栈,需要注意是否栈空
判断栈空:用STEmpty(&St)表示,常用到判断栈空,因此封装成函数,方便使用,返回值一般用bool类型,true表示栈空,false表示栈非空
读栈顶元素:用STTop(&St)表示,栈非空则返回栈顶元素
获取数据个数:用STSize(&St)表示 ,返回数据个数
2.栈的实现
用一个结构体描述这个栈的各项数据:
typedef int STDataType;
typedef struct Stack
{
STDataType* a; //栈底
int top; //栈顶
int capacity; //栈容量
}ST;
初始化栈:
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
//top指向栈顶数据的下一个位置
pst->top = 0;
pst->capacity = 0;
}
top可以指向栈顶,也可以指向栈顶的下一个位置,top的指向会影响后续的数据插入、删除、销毁,以及判空
栈的销毁:
void STDestroy(ST* pst)
{
assert(pst);free(pst->a);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
入栈:
void STPush(ST* pst, STDataType x)
{
assert(pst);//扩容
if (pst->top == pst->capacity)
{
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity* 2; //空栈则让栈空间为4
STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail");
return;
}pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;
pst->top++;
}
利用realloc的特性,空栈则执行malloc的功能
出栈:
void STPop(ST* pst)
{
assert(pst);
assert(pst->top > 0); //防止栈空
pst->top--;
}
取栈顶数据:
STDataType STTop(ST* pst)
{
assert(pst);
return pst->a[pst->top - 1]; //返回值为STDataType
}
判空:
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
获取栈的数据个数:
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
3.所有代码
以数组为例实现栈,分为头文件(Stack.h)和函数实现(Stack.c)以及测试(test.c)
Stack.h:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;//初始化栈
void STInit(ST* pst);
void STDestroy(ST* pst);//入栈 出栈
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);//取栈顶数据
STDataType STTop(ST* pst);//判空
bool STEmpty(ST* pst);//获取数据个数
int STSize(ST* pst);
Stack.c:
#include"Stack.h"//初始化栈
void STInit(ST* pst)
{assert(pst);pst->a = NULL;//top指向栈顶数据的下一个位置pst->top = 0;pst->capacity = 0;
}
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->capacity = 0;pst->top = 0;
}//入栈 出栈
void STPush(ST* pst, STDataType x)
{assert(pst);//扩容if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : pst->capacity* 2;STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail"); return;}pst->a = tmp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}
void STPop(ST* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}//取栈顶数据
STDataType STTop(ST* pst)
{assert(pst);return pst->a[pst->top - 1];
}//判空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}//获取数据个数
int STSize(ST* pst)
{assert(pst);return pst->top;
}
test.c
#include"Stack.h"
int main()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d\n", STTop(&s));STPop(&s);}STDestroy(&s);return 0;
}