数据结构——栈和队列(上)
目录
一,栈的介绍
二,栈及其操作的实现
1. 初始化空间
2. 进栈和出栈
3. 栈的其余操作
三,整体代码
一,栈的介绍
我们都知道一个杀伤力极大的武器——枪。枪击案、枪击事件屡见不鲜,即便没有见过,也会有各色各样的玩具枪,模型枪。我们今天要带来的线性表之一——栈,它类似于子弹放入弹夹一样:先进去的子弹后出来,后进去的子弹先出来。
在我们软件应用中,栈这种先进后出的数据结构的应用是非常广的。比如我们使用的浏览器
在我们浏览网页上网时,总会有一个“ 后退 ”键是以供我们使用的,假如你正在轻松的刷着视频,突然看到一个让自己很感兴趣的链接,当你迫不及待地打开它观看时却发现是假的,于是你就可以点击“后退”键返回到你的视频页面。即便你点击了十几个链接进行跳转,当你又连续单击”后退“键的时,就i可以回到之前浏览的某个页面。
对于栈的定义是:栈是限定仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。
栈又称为后进先出的线性表,简称LIFO(Last in First out) 结构。
而定义中的表尾指的不是栈底,而是栈顶,这点要牢记。
对于栈的插入操作——即给栈中放入数据,我们称之为进栈,也叫压栈。好比子弹入弹夹
对于栈的删除操作——即删除栈中的数据,我们称之为出栈,也叫弹栈。好比子弹出弹夹
其两种操作图如下展示:(因为我们以顶部底部来描绘栈,所以我们竖直其模型方便理解)
那么是不是说最先进栈的元素只能最后出栈呢?答案是不一定的,比如当1,2,3三个元素依次进栈时,我们可以1进栈接着2接着3,出栈顺序就是3、2、1。但是我们也可以1进栈后直接出,然后2进栈,2出栈,3进栈,3出栈。也可以1进,2进,2出,1出,3进,3出等等。
(注意,这里的栈不是我们空间里的栈区,前者是数据结构,后者是空间内存区)
二,栈及其操作的实现
1. 初始化空间
由上图进栈出栈的图示可知,我们需要一个变量top来记录栈顶,由于是线性表,则需要一段连续的空间。
于是对栈的基本含参实现如下:
typedef int STDatatype;
typedef struct Stack
{STDatatype* a; //开辟连续空间int capacity; //栈的大小int top; //栈内元素个数
}Stack;
我们在此基础上为其开辟四个大小为int的空间。
//初始化空间
void StackInit(Stack* ps)
{assert(ps);ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);if (ps->a == NULL){perror("malloc fail");exit(-1);}ps->capacity = 4;ps->top = 0;
}
因为要修改栈的大小,我们传入结构体指针。开辟完成后我们便得到了一个空栈,大小为16字节。
2. 进栈和出栈
我们先来实现前面所讲到的进出栈操作,这里我们push表示进栈,pop表示出栈。在初始化栈空间时,我们将top放置为0表示此时栈内没有元素,所以此时只需将元素进栈并在达到栈满容量时扩容即可,进栈实现如下:
void StackPush(Stack* ps,STDatatype x)
{assert(ps);//检查容量if (ps->top == ps->capacity){STDatatype* tmp = (STDatatype*)realloc(ps->a, 2 * ps->capacity * sizeof(STDatatype));if (tmp == NULL){perror("realloc fail");exit(-1);}ps->a = tmp;ps->capacity *= 2;}//进栈ps->a[ps->top] = x;ps->top++;
}
可以观察到我们的栈不再是原来的空栈了,我们放入了1~5五个元素并且容量变为8,此时栈顶元素为Top,也同时表示着栈中有5个元素。
再来实现出栈效果,当我们为空栈时就不能进行出栈操作,所以我们需要判断栈是否是空栈。之后便是像我们顺序表删除元素类似的操作,实现如下:
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}
可以观察到我们栈中元素只剩一个。
3. 栈的其余操作
作为一个拿的上台面的数据结构,它显然不能只有两种相关的操作,返回栈顶元素,返回栈中个数以及判断栈是否为空,销毁栈等四种操作也是极其重要的。接下来我们一一实现。
判断栈是否为空:
我们使用布尔值来反映情况,前面提到,top表示的就是栈的元素个数,所以当top为0时就是空栈,top不为零就不是空栈。相关实现如下:
bool StackEmpty(Stack* ps)
{assert(ps);return ps->top == 0;
}
返回栈顶元素:
在我们往后的学习中会有涉及到极其重要的知识——用栈来模拟递归。这时我们的返回栈顶元素操作就必不可少。注意,当栈为空栈时,我们就无需返回,所以这里可以复用我们空栈判断函数来对栈是否为空进行断言,实现如下:
STDatatype StackTop(Stack* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top-1];
}
在我们入栈五个元素并出栈四个元素后,可知栈内唯一元素就是1,所以此时我们可以提取栈顶元素。
返回栈的元素个数:
由于返回的数值一定是整数,所以我们返回值设置为int型,返回top即可。
int StackSize(Stack* ps)
{assert(ps);return ps->top;
}
销毁栈:
由于我们使用到malloc和realloc函数,它们是在栈空间上开辟内存我们仍然需要主动释放空间
实现如下:
void StackDestroy(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}
三,整体代码
这里小编只附着Stack.c和Stack.h的文件,测试文件读者可以自己复制两个Stack文件后自行创建使用。
//Stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int STDatatype;
typedef struct Stack
{STDatatype* a;int capacity;int top;
}Stack;void StackInit(Stack* ps);
void StackDestroy(Stack* ps);
void StackPush(Stack* ps, STDatatype x);
void StackPop(Stack* ps);
STDatatype StackTop(Stack* ps);
bool StackEmpty(Stack* ps);
int StackSize(Stack* ps);//Stack.c
#include"Stack.h"//初始化空间
void StackInit(Stack* ps)
{assert(ps);ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);if (ps->a == NULL){perror("malloc fail");exit(-1);}ps->capacity = 4;ps->top = 0;
}//销毁
void StackDestroy(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;
}void StackPush(Stack* ps,STDatatype x)
{assert(ps);if (ps->top == ps->capacity){STDatatype* tmp = (STDatatype*)realloc(ps->a, 2 * ps->capacity * sizeof(STDatatype));if (tmp == NULL){perror("realloc fail");exit(-1);}ps->a = tmp;ps->capacity *= 2;}ps->a[ps->top] = x;ps->top++;
}void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);//assert();ps->top--;
}//返回栈顶元素
STDatatype StackTop(Stack* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top-1];
}bool StackEmpty(Stack* ps)
{assert(ps);return ps->top == 0;
}int StackSize(Stack* ps)
{assert(ps);return ps->top;
}
这便是栈的介绍啦,希望大家多多支持。
数据结构——栈和队列(上)相关推荐
- 数据结构栈和队列_使您的列表更上一层楼:链接列表和队列数据结构
数据结构栈和队列 When you want to store several elements somewhere in a program, the go-to data type is an a ...
- 数据结构栈与队列的应用之汽车轮渡问题——自己的一些理解
本题摘自王道数据结构栈与队列的应用的课后题,题目如下: 某汽车轮渡口,过江渡船每次能载10辆汽车过江.过江车辆分为客车类和货车类,上渡船有如下规定:同类车先到先上船,客车先于货车上船,且每上4辆客车, ...
- 数据结构——栈与队列相关题目
数据结构--栈与队列相关题目 232. 用栈实现队列 思路 225. 用队列实现栈 1.两个队列实现栈 2.一个队列实现栈 20. 有效的括号 思路 1047. 删除字符串中的所有相邻重复项 思路 1 ...
- 第十章 基本数据结构——栈和队列
摘要 本章介绍了几种基本的数据结构,包括栈.队列.链表以及有根树,讨论了使用指针的简单数据结构来表示动态集合.本章的内容对于学过数据结构的人来说,没有什么难处,简单的总结一下. 1.栈和队列 栈和队列 ...
- 【数据结构-栈和队列】详解栈和队列(代码+STL+原理)
一.栈的应用 栈是一种先进后出(FILO)的数据结构 1.1 栈的操作实现 清空(clear): // 栈的清空操作就是把栈顶top置为-1 void clear(){top=-1; } // 清空栈 ...
- 基本数据结构 - 栈和队列
摘要 本章介绍了几种基本的数据结构,包括栈.队列.链表以及有根树,讨论了使用指针的简单数据结构来表示动态集合.本章的内容对于学过数据结构的人来说,没有什么难处,简单的总结一下. 1.栈和队列 栈和队列 ...
- 数据结构栈和队列的实现
数据结构的实验,栈和队列的实现. 栈的特点:先进后出,类似于一个只有一个口子,且一次只能容一个物体通过的容器,放在上面的物体必须先拿出才能拿下面的. 队列的特点:先进先出,类似于火车通过隧道,先进入隧 ...
- 数据结构——栈和队列
目录 1.栈 1.1栈的基本概念 1.2栈的顺序存储实现 1.3共享栈 1.4栈的链式存储实现 1.5栈在括号匹配中的应用 1.6栈在表达式求值中的应用 1.6.1中.前.后缀表达式 1.6.2后缀表 ...
- 数据结构----栈和队列
xdm这玩意我不会导入,只能截图了. 目录 栈篇 1.1栈 1.2.栈操作数据元素的两种动作: 2.代码实现 2.1初始化和销毁 2.2插入 2.3删除和判空 2.4返回栈顶值,计算栈长 队列篇 3. ...
- 数据结构—栈和队列经典面试题
栈和队列面试题: 实现一个栈,要求实现Push(出栈).Pop(入栈).Min(返回最小值)的时间复杂度为O(1) 使用两个栈实现一个队列 使用两个队列实现一个栈 元素出栈.入栈顺序的合法性.如入栈的 ...
最新文章
- vs2013编译 protoBuffer编译出现的问题
- IE6 IE8下背景图片不显示问题
- 阿里云物联网边缘计算加载MQTT驱动
- ibatis和hibernate
- 汽车行业用户观点主题及情感分析,深度学习方案rank1
- windows配置phpredis
- php中if函数的,【后端开发】php中if函数用法
- Express框架学习笔记-get请求中参数的获取
- 红包 mysql表设计_微信红包的设计实现
- MacOS下好用的截图软件snip
- 华为路由器怎么看是不是公网_如何查看华为路由器默认ip地址
- 5G China unicom 直放站 网管协议 实时性要求
- iWebShop 电商项目实战003----页面初始化数据测试
- Disallow self-closing on HTML void elements
- Python案例—AQI 空气质量指数
- UI设计师是做什么的?
- hdu 4544 优先队列+贪心
- 查看linux下tomcat启动日志
- 在线任意进制转换工具
- X86架构PC服务器等硬件设备