【细谈数据结构】小白都可以三分钟立马上手的“栈”讲解
作者:互联网
文章目录
今天要说的这个“栈”,可是数据结构界里有名的枪手!
诶~ 为什么会被称为枪手呢?
原来啊,栈的使用步骤,和手枪弹夹的使用步骤是一样的后进先出。所以大家就时常拿手枪弹夹的原理来解释它的原理。
下面这张动图为我们解释了,什么叫做后进先出,后压入的子弹最先打出,而最先压入的子弹最后打出。
常见操作名称
我们压入第一个子弹的地方被称为栈底,压入最后一颗子弹的地方被称为栈顶。
压子弹入弹夹时的操作被称为进栈或者压栈(push),
而退出子弹的操作被称为出栈或者弹栈(pop)。
而不包含子弹的弹夹被称为空栈。
栈的抽象数据类型
全文代码都使用C 语言实现
栈有两种表达形式,一种是使用数组来存放元素,另一种是使用链表来存放,也被称为链栈。
一、使用数组存放数据的栈结构
// SeqStack.h
typedef struct SeqStack{ // 栈的数据结构
ElementType elements[MAX_SIZE]; // 用来存储栈中的数据,MAX_SIZE 为数组大小,按需求定义
int top; // 栈顶下标,-1 时表示空栈
int length; // 栈的元素个数
}SeqStack;
1.1 常用操作:
// SeqStack.h
#include <stdio.h>
#include <stdlib.h>
#include "Element.h"
typedef struct SeqStack{
ElementType elements[MAX_SIZE]; // 用来存储栈中的数据
int top; // 栈顶,-1 时表示空栈
int length; // 栈的元素个数
}SeqStack;
/** 初始化栈 */
void InitSeqStack(SeqStack * S);
/** 压栈,返回压入结果(true/false) */
int PushSeqStack(SeqStack * S, ElementType element);
/** 出栈,用指针返回栈顶元素,返回出栈结果(ture/false) */
int PopSeqStack(SeqStack * S, ElementType * element);
/** 清空栈 */
void ClearSeqStack(SeqStack * S);
/** 判断栈是否为空,返回判断结果(ture/false) */
int stackEmpty(SeqStack * S);
/** 返回栈顶元素 */
void GetTopElement(SeqStack * S, ElementType * element);
1.2 具体实现:
// SeqStack.c
/** 初始化栈 */
void InitSeqStack(SeqStack * S){
S->top = -1; // top == -1 表示栈S 此时为空栈
S->length = 0; // 栈内元素为0 个
}
/** 压栈,返回压入结果(true/false) */
int PushSeqStack(SeqStack * S, ElementType element){
// 判断栈内是否有空间给新元素使用
if(S->top >= MAX_SIZE - 1){
printf("栈满,压栈失败!\n");
return FALSE;
}
// 先更新栈顶的下标
S->top++;
// 将元素放入栈顶
S->elements[S->top] = element;
// 栈的元素个数加一
S->length++;
return TRUE;
}
/** 出栈,用指针返回栈顶元素,返回出栈结果(ture/false) */
int PopSeqStack(SeqStack * S, ElementType * element){
// 判断栈内是否有元素可以删除
if(S->top == -1){
printf("空栈,出栈失败!\n");
return FALSE;
}
// 保存栈顶元素,*element 用来保存被删除的栈顶
*element = S->elements[S->top];
// 将栈顶元素删除,栈顶下标减一,元素个数减一
S->top--;
S->length--;
return TRUE;
}
/** 清空栈 */
void ClearSeqStack(SeqStack * S){
S->top = -1; // 重新进行一次初始化操作就行
S->length = 0;
}
/** 判断栈是否为空,返回判断结果(ture/false) */
int stackEmpty(SeqStack * S){
// 若top == -1 表示空栈,返回是/TRUE,否则返回否/FALSE
if(S->top == -1)
return TRUE;
else
return FALSE;
}
/** 返回栈顶元素 */
void GetTopElement(SeqStack * S, ElementType * element){
// 判断是否有栈顶元素,无则返回空
if(S->top == -1){
printf("空栈,返回失败!\n");
element = NULL;
}
// 将栈顶元素赋值给返回元素*element
*element = S->elements[S->top];
}
二、使用链表存放数据的链栈结构
链栈的使用相比于数组栈的使用稍微复杂一些,但是它的优点是不需要提前设定整个栈的空间大小,适用于元素个数不确定的情况。
// LinkedStack.h
typedef struct StackNode{ // 结点结构
ElementType data; // 结点中保存的元素内容
struct StackNode * next; // 指向下一个元素
}StackNode;
typedef struct LinkedStack{ // 栈的数据结构
StackNode * top; // 头结点,用来指向栈顶元素
int length; // 栈中元素个数
}LinkedStack;
2.1 常用操作:
// LinkedStack.h
#include <stdio.h>
#include <stdlib.h>
#include "Element.h"
/** 初始化链栈 */
void InitLinkedStack(LinkedStack * S);
/** 压栈,返回压入结果(true/false) */
int PushLinkedStack(LinkedStack * S, ElementType element);
/** 出栈,用指针返回栈顶元素,返回出栈结果(ture/false) */
int PopLinkedStack(LinkedStack * S, ElementType * element);
/** 清空栈 */
void ClearLinkedStack(LinkedStack * S);
/** 销毁栈 */
void DestroyLinkedStack(LinkedStack * S);
2.2 具体实现:
#include "LinkStack.h"
/** 初始化链栈 */
void InitLinkedStack(LinkedStack * S){
S->top = NULL; // 栈顶元素指向空,相当于头结点指向空,表示空栈。
S->length = 0; // 栈内元素为0 个
}
/** 压栈,返回压入结果(true/false) */
int PushLinkedStack(LinkedStack * S, ElementType element){
// 创建一个新结点,用来保存插入元素
StackNode * newnode = (StackNode *)malloc(sizeof(StackNode));
newnode->data = element;
// 插入元素的下一个元素指向当前栈顶元素
newnode->next = S->top;
// 栈顶元素更新为插入元素
S->top = newnode;
// 栈内元素加一
S->length++;
// 返回操作成功
return TRUE;
}
/** 出栈,用指针返回栈顶元素,返回出栈结果(ture/false) */
int PopLinkedStack(LinkedStack * S, ElementType * element){
// 判断栈内是否有元素删除
if(S->top == NULL){
printf("空栈,无法进行删除操作!\n");
return FALSE;
}
// 将栈顶元素保存到返回元素*element
*element = S->top->data;
// 新建一个临时结点保存待删除的栈顶元素,再通过释放临时结点达到删除操作
StackNode * node = S->top;
// 栈顶元素指向上一个插入的元素
S->top = S->top->next;
// 栈内元素个数减一
S->length--;
// 释放临时保存待删除的栈顶元素
free(node);
// 返回操作成功
return TRUE;
}
/** 清空栈 */
void ClearLinkedStack(LinkedStack * S){
// 创建一个临时结点,用来保存各个结点,再通过释放临时结点达到删除操作
StackNode * tempNode;
// 遍历整个栈,当S->top 指向NULL 时,整个栈删除完毕
while(S->top){
// 保存当前栈顶元素
tempNode = S->top;
// 将栈顶元素指向上一个插入元素
S->top = S->top->next;
// 释放保存的栈顶元素
free(tempNode);
// 栈内元素个数减一
S->length--;
}
}
/** 销毁栈 */
void DestroyLinkedStack(LinkedStack * S){
// 删除整个栈的元素
ClearLinkedStack(S);
// 再将栈给释放
free(S);
// 将栈指向NULL
S = NULL;
}
以上就是本篇文章的所有内容了,如果觉得有帮助到你的话,
麻烦动动小手,点赞收藏转发!!!
你的每一次点赞都是我更新的最大动力~
我们下期再见!
标签:三分钟,int,top,元素,栈顶,element,SeqStack,细谈,数据结构 来源: https://blog.csdn.net/weixin_43776724/article/details/114017923