计算机考研408-数据结构-栈
一. 定义
栈(Stack)是一种常见的数据结构,它是一种“后进先出”类型(Last In First Out,LIFO)的数据结构只能在栈顶进行插入和删除操作。
很经典的一个例子就是:大家在玩儿玩具枪时,总需要先将子弹压入弹夹,之后安装弹夹,进行射击。大家思考一下,我们打出的第一发子弹是不是就是我们最后压入弹夹的子弹。如图所示
(注:图片摘自CSDN博主十里坡小白的文章:数据结构 —— 栈(超详细图解 & 接口函数实现))
二. 特点
先入后出,后入先出,栈是限定仅在栈顶进行插入和删除操作的数据结构。
(注:图片摘自CSDN博主知心宝贝的文章:【图解数据结构】栈全面总结)
三. 原理及实现
- 数组形式(顺序栈)
(注:图片摘自CSDN博主十里坡小白的文章:数据结构 —— 栈(超详细图解 & 接口函数实现))
顺序栈结构体定义(静态)
#define n 500//定义顺序栈大小
struct stack
{
int top;//栈顶指针
int a[n];//顺序栈数组
}SeqStack;
初始化栈
void InitStack(SeqStack *S)
{
S->top = -1;//构造一个空栈S
}
判断栈空
int IsEmpty(SeqStack *S)
{
return(S->top==-1?TRUE:FALSE);
}
判断栈满
int IsFull(SeqStack *S)
{
return(S->top==Stack_Size-1?TRUE:FALSE);
}
取栈顶元素
int GetTop(SeqStack *S,StackElementType *x)
{
if(S->top == -1)//栈为空
return(FALSE);
else
{
*x = S->elem[S->top];
return(TRUE);
}
}
入栈
int Push(SeqStack *S,StackElementType *x)
{
if(S->top == 1)//栈为满
return(FALSE);
else
{
*x = S->elem[S->top];
S->top++;
return(TRUE);
}
}
出栈
int Pop(SeqStack *S,StackElementType *x)
{
if(S->top == -1)//栈为空
return(FALSE);
else
{
*x = S->elem[S->top];
S->top--;
return(TRUE);
}
}
2. 链表形式(栈链)
顺序栈结构体定义(静态)
typedef struct StackNode {
int data;//存放栈中元素
struct StackNode *Lhead;//栈顶指针 ,记录栈顶元素的位置
} *LinkStack;//链栈的类型定义
初始化栈
bool InitStack(LinkStack &S) {//链栈的初始化,初始化一个空栈
S=NULL;
return true;
}
判断栈空
bool EmptyStack(LinkStack S){
if(S==NULL)
return true;
else
return false;
}
取栈顶元素
bool GetTopStack(LinkStack &S,int &x) {
if(S==NULL)
return false;
x=S->data;
return true;
}
入栈
void PushStack(LinkStack &S, int x) {
StackNode *p;
p = (StackNode*)malloc(sizeof(StackNode));//动态分配创建一个新结点p
p->data = x; //将x放入新结点p的数据域中
p->Lhead = S; //将新结点p插入到当前链栈的栈顶前
S = p; //将新结点p作为栈顶元素
}
出栈
/*出栈(删除操作)*/
bool PopStack(LinkStack &S,int &x) {
StackNode *p;
if(S==NULL)//若栈为空,则报错
return false;
x=S->data;//x记录当前栈顶元素
p=S;//p指针指向原栈顶
S=S->Lhead;//S指向下一个结点
free(p);//释放栈顶元素
return true;
}
四. 代码实现
Stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
// 动态的栈
typedef int STDataType;
struct Stack
{
STDataType* a;
int top; //栈顶
int capacity; //容量,方便增容
};
typedef struct Stack Stack;
//同样传指针,形参改变不影响实参,实参传过去是它的拷贝
void StackInit(Stack* pst); //初始化
void StackDestory(Stack* pst); //销毁
//性质决定在栈顶出入数据
void StackPush(Stack* pst, STDataType x); //入栈
void StackPop(Stack* pst); //出栈
//取栈顶的数据
STDataType StackTop(Stack* pst);
// 空返回1,非空返回0
//int StackEmpty(Stack* pst);
bool StackEmpty(Stack* pst); //判断栈是否为空
int StackSize(Stack* pst); //统计栈中的数据
Stack.c
#include"Stack.h"
void StackInit(Stack* pst)
{
assert(pst);
/*pst->a = NULL;
pst->capacity = 0;
pst->top = 0;*/
pst->a = (STDataType*)malloc(sizeof(STDataType)*4);
pst->capacity = 4;
pst->top = 0;
}
void StackDestory(Stack* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = pst->top = 0;
}
void StackPush(Stack* pst, STDataType x)
{
if (pst->top == pst->capacity)
{
STDataType* tmp = (STDataType*)realloc(pst->a,sizeof(STDataType)*(pst->capacity * 2));
if (tmp == NULL)
{
printf("realloc失败\n");
exit(-1); //结束程序
}
pst->a = tmp;
pst->capacity *= 2;
}
pst->a[pst->top] = x;
pst->top++;
}
void StackPop(Stack* pst)
{
assert(pst);
assert(!StackEmpty(pst));
pst->top--;
}
STDataType StackTop(Stack* pst)
{
assert(pst);
assert(!StackEmpty(pst));
return pst->a[pst->top - 1];
}
bool StackEmpty(Stack* pst)
{
assert(pst);
return pst->top == 0;
}
int StackSize(Stack* pst)
{
assert(pst);
return pst->top ;
}
Test.c
#include"Stack.h"
void TestStack()
{
Stack st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
printf("%d \n", StackSize(&st));
while (!StackEmpty(&st))
{
printf("%d ", StackTop(&st));
StackPop(&st);
}
StackDestory(&st);
}
int main()
{
TestStack();
}