目录
栈的概念及结构
栈的实现
栈的初始化
栈的销毁
压栈
出栈
返回栈顶的元素
统计栈中的元素个数
判断栈是否为空
栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一段进行插入和删除元素操作。进行数据插入和删除操作的一段被称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
它这个结构有点类似于子弹的弹夹,我们在填充弹夹的时候,子弹是从上压进去的,当我们开枪的时候先打出来的是后压进去的子弹。
栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
下面我们就使用数组来实现数组栈吧。
栈的函数接口声明
#pragma once #include#include #include #include typedef int STDataType; typedef struct Stack { STDataType* a; int top;//栈顶的位置 int capacity;//栈的空间容量 }ST; //初始化 void StackInit(ST* ps); //销毁 void StackDestroy(ST* ps); //压栈 void StackPush(ST* ps, STDataType x); //出栈 void StackPop(ST* ps); //返回栈顶的元素 STDataType StackTop(ST* ps); //统计栈中的元素个数 int StackSize(ST* ps); //判断栈是否为空 bool StackEmpty(ST* ps);
栈的初始化
刚开始数组还未开辟,所以先将其置为NULL,capacity为0。这里的top可以为0或者-1,作者选择的是top=0的方式初始化
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;//ps->top = -1;
ps->capacity = 0;
}
栈的销毁
//销毁
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = 0;
ps->top = 0;
}
压栈
压栈的时候我们首先需要判断栈是否已经满了,若满了就增容,没满空间足够直接压栈即可。
//压栈
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//空间不够就需要扩容
if (ps->top == ps->capacity)
{
int Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType)*Newcapacity);
if (temp == NULL)
{
printf("realloc failn");
exit(-1);
}
ps->a = temp;
ps->capacity = Newcapacity;
}
//空间足够就直接压栈
ps->a[ps->top] = x;
ps->top++;
}
出栈
出栈的时候,栈一定不能为空,否则后面再入栈或者打印的时候就会发生错误。因此我们需要加上一个断言或者调用一个判断空栈的函数即可。
//出栈
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//assert(ps->top > 0);
ps->top--;
}
返回栈顶的元素
同样的这里我们也需要加上断言或者调用判断空栈的函数来保证栈不为空。
//返回栈顶的元素
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//assert(ps->top > 0);
return ps->a[ps->top - 1];
}
统计栈中的元素个数
top正好就是我们需要的Size,因此返回top即可
//统计栈中的元素个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
判断栈是否为空
实现这个函数我们有以下的两种方式。作者更倾向于第二种,因为它只有一行感觉它更香。
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
if (ps->top == 0)
//{
// return true;
//}
//else
//{
// return false;
//}
return ps->top == 0;
}
刚开始数组还未开辟,所以先将其置为NULL,capacity为0。这里的top可以为0或者-1,作者选择的是top=0的方式初始化
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;//ps->top = -1;
ps->capacity = 0;
}
//销毁
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = 0;
ps->top = 0;
}
压栈
压栈的时候我们首先需要判断栈是否已经满了,若满了就增容,没满空间足够直接压栈即可。
//压栈
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//空间不够就需要扩容
if (ps->top == ps->capacity)
{
int Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType)*Newcapacity);
if (temp == NULL)
{
printf("realloc failn");
exit(-1);
}
ps->a = temp;
ps->capacity = Newcapacity;
}
//空间足够就直接压栈
ps->a[ps->top] = x;
ps->top++;
}
出栈
出栈的时候,栈一定不能为空,否则后面再入栈或者打印的时候就会发生错误。因此我们需要加上一个断言或者调用一个判断空栈的函数即可。
//出栈
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//assert(ps->top > 0);
ps->top--;
}
返回栈顶的元素
同样的这里我们也需要加上断言或者调用判断空栈的函数来保证栈不为空。
//返回栈顶的元素
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//assert(ps->top > 0);
return ps->a[ps->top - 1];
}
统计栈中的元素个数
top正好就是我们需要的Size,因此返回top即可
//统计栈中的元素个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
判断栈是否为空
实现这个函数我们有以下的两种方式。作者更倾向于第二种,因为它只有一行感觉它更香。
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
if (ps->top == 0)
//{
// return true;
//}
//else
//{
// return false;
//}
return ps->top == 0;
}
压栈的时候我们首先需要判断栈是否已经满了,若满了就增容,没满空间足够直接压栈即可。
//压栈
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//空间不够就需要扩容
if (ps->top == ps->capacity)
{
int Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType)*Newcapacity);
if (temp == NULL)
{
printf("realloc failn");
exit(-1);
}
ps->a = temp;
ps->capacity = Newcapacity;
}
//空间足够就直接压栈
ps->a[ps->top] = x;
ps->top++;
}
出栈的时候,栈一定不能为空,否则后面再入栈或者打印的时候就会发生错误。因此我们需要加上一个断言或者调用一个判断空栈的函数即可。
//出栈 void StackPop(ST* ps) { assert(ps); assert(!StackEmpty(ps)); //assert(ps->top > 0); ps->top--; }
返回栈顶的元素
同样的这里我们也需要加上断言或者调用判断空栈的函数来保证栈不为空。
//返回栈顶的元素
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//assert(ps->top > 0);
return ps->a[ps->top - 1];
}
统计栈中的元素个数
top正好就是我们需要的Size,因此返回top即可
//统计栈中的元素个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
判断栈是否为空
实现这个函数我们有以下的两种方式。作者更倾向于第二种,因为它只有一行感觉它更香。
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
if (ps->top == 0)
//{
// return true;
//}
//else
//{
// return false;
//}
return ps->top == 0;
}
同样的这里我们也需要加上断言或者调用判断空栈的函数来保证栈不为空。
//返回栈顶的元素
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//assert(ps->top > 0);
return ps->a[ps->top - 1];
}
top正好就是我们需要的Size,因此返回top即可
//统计栈中的元素个数 int StackSize(ST* ps) { assert(ps); return ps->top; }
判断栈是否为空
实现这个函数我们有以下的两种方式。作者更倾向于第二种,因为它只有一行感觉它更香。
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
if (ps->top == 0)
//{
// return true;
//}
//else
//{
// return false;
//}
return ps->top == 0;
}
实现这个函数我们有以下的两种方式。作者更倾向于第二种,因为它只有一行感觉它更香。
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
if (ps->top == 0)
//{
// return true;
//}
//else
//{
// return false;
//}
return ps->top == 0;
}
栈的测试:
void TestStack2()
{
ST st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
StackPush(&st, 5);
printf("%d ", StackTop(&st));
StackPop(&st);
StackPush(&st, 6);
printf("%d ", StackTop(&st));
StackPop(&st);
while (!StackEmpty(&st))
{
printf("%d ", StackTop(&st));
StackPop(&st);
}
StackDestroy(&st);
}
int main()
{
//TestStack();
TestStack2();
return 0;
}



