今天为大家分享的是栈的模拟实现,本文主要讲解如何以数组的形式模拟实现,同时给出链表模拟实现栈的代码。
目录
- 图解栈的结构
- 数组模拟栈的分步实现
- 创建并初始化
- 入栈
- 检测栈是否为空
- 出栈
- 获取栈顶元素
- 获取栈内有效元素个数
- 销毁栈
- 链表模拟实现栈
- 模拟思路
- 总体代码(函数名同数组模拟栈)
图解栈的结构
对于栈,我们可以用八个字简要概括“先入后出,后入先出”。"栈"就像一个木桶,最先放进去的被后放进去的压住,想要拿出就必须先把顶上的拿出。
数组模拟栈的分步实现
理解之后就很好实现了,下面让我们来实现“栈”的各个步骤吧。
创建并初始化
我们定义一个栈,需要用数组来模拟,也就需要记录下数组的头指针,还需要确定栈的容量和当前存储量,为此需要两个int类型的变量来记录栈顶位置和栈的容量大小。
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
// 初始化栈
void StackInit(Stack* ps)
{
assert(ps);
ps->_a = NULL;
ps->_capacity = ps->_top = 0;
}
入栈
入栈的过程就是将新的元素放到栈的最顶端,然后移动栈顶元素,即改变记录的栈顶元素下标。不过在入栈之前,需要注意的一点是检查栈是否还有剩余空间,如果没有就需要扩容。
// 入栈
void StackPush(Stack* ps, STDataType data)
{
assert(ps);
if (ps->_capacity == ps->_top)
{
ps->_capacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
ps->_a = (STDataType*)realloc(ps->_a, ps->_capacity * sizeof(STDataType));
assert(ps->_a);
}
ps->_a[ps->_top] = data;
ps->_top++;
}
检测栈是否为空
在出栈的时候,需要注意下当我们栈内已经没有元素的时候,就无法继续元素出栈了。
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{
assert(ps);
return ps->_top == 0;
}
出栈
出栈并不需要移除栈顶元素(下图一),我们只需要改变记录的栈顶元素下标即可(下图二)。同时不要忘记判断栈是否为空。
// 出栈
void StackPop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->_top--;
}
获取栈顶元素
由于在结构体内记录了栈顶元素下标,因此我们很容易就可以得到栈顶元素。
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->_a[ps->_top - 1];
}
获取栈内有效元素个数
既然记录了栈顶元素下标,那么由于此处的数组是一顺序表,因此栈顶元素下标即是栈内有效元素的个数。
// 获取栈内有效元素个数
int StackSize(Stack* ps)
{
assert(ps);
return ps->_top;
}
销毁栈
销毁栈的时候需要注意,不要忘记将数组的指针置为空哦。
// 销毁栈
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->_a);
ps->_a = NULL;
ps->_capacity = ps->_top = 0;
}
链表模拟实现栈
模拟思路
运用链表我们也需要完成“先入后出,后入先出”,这就表示我们记录的指针必须一直指向最新入栈的结点,同时这个结点出栈之后,下一个结点必须是前一个入栈的结点,于是便可以利用头插法的单链表来模拟实现栈。下面可以对比一下数组(图一)和链表(图二)分别模拟实现栈的具体结构。
总体代码(函数名同数组模拟栈)
#include<iostream>
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int STDataType;
typedef struct node
{
STDataType x;
struct node* next;
}node;
typedef struct Stack
{
node* head;
int nums; // 长度
}Stack;
// 初始化栈
void StackInit(Stack* ps)
{
assert(ps);
ps->head = NULL;
ps->nums = 0;
}
// 入栈
void StackPush(Stack* ps, STDataType data)
{
assert(ps);
node* new_node = (node*)malloc(sizeof(node));
new_node->x = data;
new_node->next = ps->head;
ps->head = new_node;
ps->nums++;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{
assert(ps);
return ps->nums == 0;
}
// 出栈
void StackPop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
node* del = ps->head;
ps->head = ps->head->next;
free(del);
ps->nums--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->head->x;
}
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
assert(ps);
return ps->nums;
}
// 销毁栈
void StackDestroy(Stack* ps)
{
assert(ps);
node* tmp = ps->head;
while (tmp)
{
ps->head = ps->head->next;
free(tmp);
tmp = ps->head;
}
ps->head = NULL;
ps->nums = 0;
}
int main()
{
Stack sta;
StackInit(&sta);
StackPush(&sta, 1);
StackPush(&sta, 2);
StackPush(&sta, 3);
StackPush(&sta, 4);
StackPush(&sta, 5);
std::cout << StackSize(&sta) << std::endl;
while (!StackEmpty(&sta))
{
printf("%d", StackTop(&sta));
StackPop(&sta);
}
}