数据结构之栈
数据结构之栈
什么是栈?
今天,我将具体分析栈。什么是栈,与链表不一样,打个比方。栈就像是一堆书,叠在一起,如果你要取最下面的一本书出来,那么,你首先要做的就是将这本书上方的书移开,才可以拿这本书。同理,想要这一系列的书本复原,你需要做的就是一本一本书往上叠。这个过程就是栈中存取数据的过程。
搜索引擎查找关于栈的相关定义,堆栈(英语:stack)又称为栈或堆叠,是计算机科学中的一种抽象资料类型,只允许在有序的线性资料集合的一端(称为堆栈顶端,英语:top)进行加入数据(英语:push)和移除数据(英语:pop)的运算。因而按照后进先出(LIFO, Last In First Out)的原理运作。
与栈类似又不一样的就是队列了,什么是队列,简单讲下,与栈不同的地方就是先进先出。以后我会详细介绍。
栈与队列的用法有很多,栈常用于深度优先搜索,逆波兰计算器(有空我会专门写一篇博文来介绍逆波兰算法),队列常用于广度优先搜索。栈的用途还有很多,比如我们浏览器浏览网站时,常常有回退,回头功能就是通过栈来完成的,还有我们平时常用的递归,也是通过栈来完成的,需要递归的算法,我们都可以讲其改成非递归实现。
与链表类似,栈也可以分成顺序栈和链栈,我们常用的也是链栈。
图解栈

这就是栈,数据只能从一端进,也从这一端出。
常见的有链栈和顺序栈,链栈的和上一节的线性表一样,不必考虑生成的栈的长度,增加一个结点,申请一块内存空间。
下面我们来看一看链栈的入栈图解
- 生成新结点
- 新结点的后继直接指向当前的栈顶结点
- 栈顶指针直接指向新结点

出栈操作类似,不一一举例。
栈的常用操作
顺序栈 ADT
Status initStack(SqStack *s,int sizes);//初始化栈
Status IsEmptyStack(SqStack *s);//判断栈是否为空
Status getTopStack(SqStack *s,ElemType *e);//获取栈顶元素
Status clearStack(SqStack *s);//清空栈
Status destoryStack(SqStack *s);//销毁栈
Status StackLength(SqStack *s);//获取栈的长度
Status pushStack(SqStack *s,ElemType data);//入栈
Status popStack(SqStack *s,ElemType *data);//出栈
上述的是顺序栈,链栈的基本操作也是如此,只需要稍微改动一下即可。
顺序栈的实现
头文件
/*filename:SqStack.h*/
#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
typedef enum Status
{
ERROR = 0, SUCCESS = 1
} Status;
typedef int ElemType;
typedef struct SqStack
{
ElemType *elem;
int top;
int size;
} SqStack;
//基于数组的顺序栈
Status initStack(SqStack *s,int sizes);//初始化栈
Status isEmptyStack(SqStack *s);//判断栈是否为空
Status getTopStack(SqStack *s,ElemType *e); //得到栈顶元素
Status clearStack(SqStack *s);//清空栈
Status destroyStack(SqStack *s);//销毁栈
Status stackLength(SqStack *s,int *length);//检测栈长度
Status pushStack(SqStack *s,ElemType data);//入栈
Status popStack(SqStack *s,ElemType *data);//出栈
#endif
源文件
#include "SqStack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Status initStack(SqStack* s, int sizes)//初始化栈
{
s->elem = (ElemType*)malloc(sizeof(ElemType) * sizes);
s->top = -1;
s->size = sizes;
}
Status isEmptyStack(SqStack* s)//判断栈是否为空
{
if (s->top == 0)
return SUCCESS;
}
Status getTopStack(SqStack* s, ElemType* e) //得到栈顶元素
{
if (s->top == -1)
return ERROR;
*e = s->elem[s->top];
return SUCCESS;
}
Status clearStack(SqStack* s)//清空栈
{
if (s->top == -1)
return ERROR;
s->top = -1;
return SUCCESS;
}
Status destroyStack(SqStack* s)//销毁栈
{
free(s->elem);
s->top = 0;
s->size = 0;
return SUCCESS;
}
Status stackLength(SqStack* s, int* length)//检测栈长度
{
*length = s->top+1;
return SUCCESS;
}
Status pushStack(SqStack* s, ElemType data)//入栈
{
if (s->top == s->size - 1)/*判断栈是否已满*/
return ERROR;
s->top++;
s->elem[s->top] = data;
return SUCCESS;
}
Status popStack(SqStack* s, ElemType* data)//出栈
{
if (s->top == -1)
return ERROR;
*data = s->elem[s->top];
s->top--;
return SUCCESS;
}
链式栈的实现
头文件
#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
#define NULL 0
typedef enum Status
{
ERROR = 0,
SUCCESS = 1
} Status;
typedef int ElemType;
typedef struct StackNode
{
ElemType data;
struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
//链栈
Status initLStack(LinkStack *s);//初始化栈
Status isEmptyLStack(LinkStack *s);//判断栈是否为空
Status getTopLStack(LinkStack *s,ElemType *e);//得到栈顶元素
Status clearLStack(LinkStack *s);//清空栈
Status destroyLStack(LinkStack *s);//销毁栈
Status LStackLength(LinkStack *s,int *length);//检测栈长度
Status pushLStack(LinkStack *s,ElemType data);//入栈
Status popLStack(LinkStack *s,ElemType *data);//出栈
#endif
源文件
#include "LinkStack.h"
#include <stdio.h>
Status initLStack(LinkStack* s)//初始化栈
{
LinkStackPtr S = (LinkStackPtr)malloc(sizeof(StackNode));
S->next = NULL;
s->top = S;
s->count = 0;
}
Status isEmptyLStack(LinkStack* s)//判断栈是否为空
{
if (s->count == 0)
return SUCCESS;
return ERROR;
}
Status getTopLStack(LinkStack* s, ElemType* e)//得到栈顶元素
{
if (s->count == 0)
return ERROR;
else
*e = s->top->data;
return SUCCESS;
}
Status clearLStack(LinkStack* s)//清空栈
{
if (s->count == 0)
return ERROR;
ElemType e;
for (int i = s->count; i > 0; i--)
{
popLStack(s, &e);
}
return SUCCESS;
}
Status destroyLStack(LinkStack* s)//销毁栈
{
if (isEmptyLStack(&s))
return ERROR;
while (s->top!=NULL)
{
LinkStackPtr p = s->top;
s->top = s->top->next;
free(p);
}
s->count = 0;
return SUCCESS;
}
Status LStackLength(LinkStack* s, int* length)//检测栈长度
{
*length = s->count;
return SUCCESS;
}
Status pushLStack(LinkStack* s, ElemType data)//入栈
{
LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
if (p == NULL)
{
printf("动态分配内存失败!\n");
return ERROR;
}
p->data = data;
p->next = s->top;
s->top = p;
s->count++;
return SUCCESS;
}
Status popLStack(LinkStack* s, ElemType* data)//出栈
{
*data = s->top->data;
LinkStackPtr p = s->top;
s->top = s->top->next;
free(p);
s->count--;
return SUCCESS;
}
忘记提醒大家了,注意,申请内存空间后后一定要记得free,否则会造成内存泄露。如果泄露了,以后这块内存就无法再使用了。

浙公网安备 33010602011771号