算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)
数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用。因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列。本篇博客其实就是《数据结构之线性表的顺序存储于链式存储(Swift面向对象版)》这篇博客的应用。本篇博客会分别给出队列的顺序和链式存储,以及栈的顺序和链式存储。
说到栈和队列这两种数据结构,理解起来应该不难。队列就是进行排队的数据结构,一个队列肯定是线性结构了,之所以称之为队列,是因为有着先入先出(FIFO ----first in first out)的特性。就像你去银行办业务排队时,你先排的队当然是你先办理业务,那些后排队的要在你后边办业务。而栈就与队列相反了,栈具有先入后出(FILO -- first in last out)的特性。在现实生活中手枪的子弹夹就是栈的结构,最先进去的子弹会最后才射出。当然在我们做iOS开发时,会经常使用到导航栈,而导航栈中存储的就是你之前Push进的页面,也是先入后出的特性。关于栈和队列,下方会给出详细的介绍。
一、栈与队列的综述
栈与队列毫无疑问都是线性结构的,分别适用于不同的场景。博客的本部分会给出栈与队列的总体介绍,然后分别给出其实现方案。当然下方在栈与队列的实现中,我们依然采用“面向接口”编程的思想,会先定义栈与队列的相关接口,然后给出栈与队列的不同实现方案。
下方这个就是一个典型的队列的结构。需要加入队列中的元素是往队尾添加的,而需要出队的元素从队头出。这样出队列的顺序与进入队列的顺序是一致的。这也就是队列的特性,先入先出。之前我们在聊GCD的中的队列的时候也同样适应这个特性。在GCD中无论是串行队列还是并行队列,其都遵循队列“先入先出”的规则。
上面我们简单的聊了一下队列,接下来我们来简单的聊一下栈。在博客的开头也提到了,弹构就是栈结构。弹夹中的子弹就是栈中的元素,遵循着先入后出的原则。下方这个示例图就是一个典型的栈型结构。在栈中有一个指针Top,永远指向栈顶元素,如果栈为空,那么Top就为nil。在栈结构中无论是入栈还是出栈,都是操作栈顶元素。所以入栈顺序与出栈顺序是相反的。
二、线性队列和链式队列的实现
聊完原理,接下来我们就要来进行代码实现了。下方将会给出具体的队列的实现代码,并给出相应的测试用例。当然我们依然是采用面向对象的思想来实现的队列的。在看具体代码之前,我们先来看一下我们本篇博客所涉及Demo的具体目录。最上面的框是两个协议,StackProtocol中声明了栈结构所涉及的操作,所有栈都要遵循该协议。QueueProtocol声明了队列中所涉及的所有操作,队列的实现都要遵循该队列协议。
这样做的好处就是所有类型的栈可以共用栈的测试用例,而队列也是如此。下方就是我们测试用例的调用方式,需要测栈时,就给栈的测试用例传入相应栈的对象,队列也是一样。也就能明显看出面向接口编程的好处。
1.队列协议:QueueType
在具体实现队列之前,我们先定义队列的接口。此处我们要定义的就是QueueType协议,在QueueType中声明的是队列的全部操作。无论是栈队列,还是顺序队列都必须要遵循该接口,而在外部声明队列类型时,我们一般会使用QueueType来声明队列类型。类型为QueueType的队列可以被赋值为遵循QueueType协议的类的任何对象。下方就是QueueType协议中的内容。
从下方的代码段中,我们显然可以看出QueueType协议就是赋值为我们的队列实现定制大纲的。有了这个大纲,具体队列的实现要按照下方这个大纲来。至于队列的具体实现细节,QueueType协议并不关心,QueueType关系的是队列对外的使用方式。
2.顺序队列
接下来我们就依据上述的队列的协议,给出顺序队列的具体实现代码。顺序队列我们就以Swift中的数组类型来代替了。enQueue--入队列所对应的操作就是往数组的尾部添加数据,而deQeueu--出队列操作就是将数组第一个元素进行移除并返回移除的值即可。下方就是入队列和出队列的操作,如下所示。队列的其他操作在此就不做过多赘述了,请参考github上分享的代码。
3.链式队列
链式队列其实就是链表的一种使用方式。链式队列就是讲队列元素以链表的形式进行存储,并且规定只能从链表的尾部添加元素,从链表的头部移除元素。关于链表的各种操作请参考上篇博客《数据结构之线性表的顺序存储于链式存储(Swift面向对象版)》中介绍的内容。该部分就是链表在队列中的应用。与上面的内容类似,下方是链式队列的核心操作,下方截图中的代码段是链式队列中出队列和入队列的操作了。如下所示:
4.队列的测试用例
上面我们分别实现了链式队列和顺序队列,接下来我们将会对上面这两种队列进行测试。由于上面这两种队列有种统一的对外调用接口,也就是这两种队列都遵循QeueuType这个队列协议。所以在测试队列时我们可以使用同一个测试用例,这也就是“面向接口编程”的好处。当我们再引入其他队列的具体实现方案时,只需要将新引入的队列解决方案遵循我们之前定义的QueueType接口即可,我们的测试用例仍然好用。从这一点我们就能看出“面向接口”编程的可维护性和高扩展性。
下方就是我们队列的测试用例, 函数的参数是QueueType的类型。也就是只要遵循QueueType协议的所有类的对象都可以作为该函数的参数。最下方的两行代码是该函数的调用方式。第一个传入的是顺序队列的对象,所有测试的就是顺序队列相关代码。而第二个传入的是栈队列的对象,那么测试的就是栈队列的相关代码。
下方就是测试用例的运行结果,先将a, b出队列,然后将x,y,x如队列。
三、栈的顺序存储与链式存储
上面已经聊完队列的相关内容了,接下来我们在按照上面的方式来聊一下栈的内容。再重复一遍栈的规则:先入后出。先入后出是栈的特定,当然栈也属于逻辑结构中线性结构,基于线性结构的特定,所以栈也是有这链式和顺序存储的结构的。下方将会给出栈的这两种实现。在具体实现不同类型的栈时,我们还是依照“面向接口”编程的思想,先定义出栈的协议StackType。StackType协议中定义了栈的所有相关操作,栈的具体实现要遵循该协议。这样做的好处就不做过多赘述了。
1.栈协议StackType的定义
首先我们还是来定义栈的接口StackType。下方截图中的代码段就是我们定义好的栈的接口,也就是Swift语言中的协议。从下方协议中我们不难看出,只声明了方法,而没有具体实现。具体实现我们放在不同类型的栈中去做。因为具体实现的栈要对外统一调用接口,所以必须遵循StackType协议。
2.栈的顺序存储实现
定义完栈的协议后,我们就该遵循该协议给出具体的实现了,接下来我们要给出顺序栈的实现方式。此处为了简单期间,我们就使用Swift的数组(Array)变量来实现。当然入栈和出栈操作都是借助Array自带的操作来实现的。下方截图中就是顺序栈中入栈(push)和出栈(pop)的操作。因为我们借助了Array本身的操作,也就是Array为我们做了许多事情,所以实现起来就比较简单了。
下方就是顺数栈的主要操作,push()方法就是将该函数的参数进行入栈操作。其实就是调用的Array的append()方法,将该参数存入到数组的最后一个位置。而pop()方法负责移除并返回栈顶元素,此处我们借用了Swift语言中的Array的removeLast()方法,来移除数组的最后一个元素,然后将这个元素进行返回。从上述操作步骤来看,栈的特点就是对栈顶元素进行操作。
3. 栈的链式存储实现
上面的顺序存储,我们使用的是顺序存储,借助了Array来实现的,所以操作起来比较简单。栈的链式存储操作起来会相对麻烦一些,不过这些操作在上篇博客中已经进行了详细的介绍,所以对本篇博客来说并非难事。
下方这段代码就是链式存储的栈的核心操作。push()方法赋值的就是往栈中添加新的元素,首先会创建一个新的结点,然后添加到栈顶元素中。栈顶元素我们用top指针来进行标记。入栈后我们还要将栈的长度进行加一操作。然后就是pop()出栈操作了,首先会判断栈是否为空,如果不为空就返回栈顶元素,并将栈顶元素进行移除。移除栈顶元素后需要将top指针指向新的栈顶并将栈中的元素进行减一操作。具体代码如下所示。
4.栈的测试用例
因为上述我们栈的实现都遵循了我们事先定义好的StackType协议,所以上述两种类型的栈可以使用一个测试用例。这一点与上述队列的测试用例是一致的,接下来我们将要来测试我们的栈。下方testStack()函数就是我们栈的测试函数,函数的参数类型是StackType。所有遵循StackType协议的栈的对象都可以作为该函数的参数。最后两行是函数的调用方式,第一个传入的是顺序栈的对象,第二个传入的参数是链栈的对象。
由上面这段代码可看出,该测试用例是适用于StackType系列的栈。下方就是测试用例的输出结果,输出结果还算是直观形象,所以在此就不做过多的赘述了。
至此呢,我们的栈与队列的顺序存储和链式存储就聊完了。当然,本篇博客只是拿出了Demo的一部分来讲的,更完整的示例还是看github上分享的Demo吧。
github分享地址:https://github.com/lizelu/DataStruct-Swift/tree/master/StackAndQueue
算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)的更多相关文章
- 算法与数据结构(一) 线性表的顺序存储与链式存储(Swift版)
温故而知新,在接下来的几篇博客中,将会系统的对数据结构的相关内容进行回顾并总结.数据结构乃编程的基础呢,还是要不时拿出来翻一翻回顾一下.当然数据结构相关博客中我们以Swift语言来实现.因为Swift ...
- 图解堆算法、链表、栈与队列(Mark)
原文地址: 图解堆算法.链表.栈与队列(多图预警) 堆(heap),是一类特殊的数据结构的统称.它通常被看作一棵树的数组对象.在队列中,调度程序反复提取队列中的第一个作业并运行,因为实际情况中某些时间 ...
- 学习javascript数据结构(一)——栈和队列
前言 只要你不计较得失,人生还有什么不能想法子克服的. 原文地址:学习javascript数据结构(一)--栈和队列 博主博客地址:Damonare的个人博客 几乎所有的编程语言都原生支持数组类型,因 ...
- python数据结构之栈与队列
python数据结构之栈与队列 用list实现堆栈stack 堆栈:后进先出 如何进?用append 如何出?用pop() >>> >>> stack = [3, ...
- 数据结构队列的java实现,包括线性和链式两种方式
实现的思路为: 采用泛型的方式,首先定义了一个Queue的接口,然后通过实现该接口实现了线性和链式的两种形式的队列: 接口代码如下: package com.peter.java.dsa.interf ...
- [ACM训练] 算法初级 之 数据结构 之 栈stack+队列queue (基础+进阶+POJ 1338+2442+1442)
再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习. 首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个 ...
- JS数据结构的栈和队列操作
数据结构:列表.栈.队列.链表.字典.散列.图和二叉查找树! 排序算法:冒牌.选择.插入.希尔.归并和快速! 查找算法:顺序查找和二分查找 在平时工作中,对数组的操作很是平常,它提供了很多方法使用,比 ...
- 数据结构之栈和队列及其Java实现
栈和队列是数据结构中非常常见和基础的线性表,在某些场合栈和队列使用很多,因此本篇主要介绍栈和队列,并用Java实现基本的栈和队列,同时用栈和队列相互实现. 栈:栈是一种基于“后进先出”策略的线性表.在 ...
- 【PHP数据结构】栈和队列的应用
通过栈和队列的学习,我们似乎会感觉到其实数据结构还是非常简单的嘛.当然,这只是一个开始,我们从顺序表.链表开始,到现在的栈和队列,其实都是为了将来在铺路.在树和图的遍历算法中,都可以见到栈和队列的身影 ...
随机推荐
- .net 操作excel
.net 操作excel的常用组件:EPPlus,NPOI 1.NPOI,即POI的.NET版本(POI是一套用Java写成的库,能够帮助开发者在没有安装微软Office的情况下读写Office文件, ...
- 搭建Linux运行环境-虚拟机
1.虚拟机软件介绍 虚拟机(Virtual Machina)软件就是一套特殊的软件,它可以作为系统独立运行,也可以运行与系统之上. 若是运行与系统之上的虚拟机软件,在一台电脑(PC或笔记本等)上安装虚 ...
- pycharm远程调试服务器
1.下载专业版pycharm并激活 https://blog.csdn.net/weixin_39332299/article/details/79692283 2.创建项目,设置解释器时,选择SSH ...
- Ajax原理一篇就够了
Ajax原理一篇就够了 一.什么是Ajax Ajax(Asynchronous JavaScript and XML的缩写)是一种异步请求数据的web开发技术,对于改善用户的体验和页面性能很有帮助.简 ...
- python requests模拟登陆正方教务管理系统,并爬取成绩
最近模拟带账号登陆,查看了一些他人的博客,发现正方教务已经更新了,所以只能自己探索了. 登陆: 通过抓包,发现需要提交的值 需要值lt,这是个啥,其实他在访问登陆页面时就产生了 session=req ...
- 1、阿里云ECS内部机器端口被100.117.90段的ip疯狂扫描导致业务异常
故障现象: 解决方案: 1.临时解决 iptables -I INPUT -s 100.117.0.0/12 -j DROP 2.后续解决 提交工单,寻找阿里服务. 后续定位是以前配置过的SLB在搞鬼 ...
- scrapy+mongodb
我们都知道scrapy适合爬取大量的网站信息,爬取到的信息储存到数据库显然需要更高的效率,scrapy配合mongodb是非常合适的,这里记录一下如何在scrapy中配置mongodb. 文件结构 $ ...
- 【JAVA】高并发优化细节点
高并发优化细节点: 微服务化 如何发现系统瓶颈? 如何高效利用有限内存: 使用基本类型 使用数组,不用集合 自定义map与数据结构 Integer—>int, Set<Intege ...
- 【pG&&CYH-01】元旦联欢会
题解: t1: 题解是循环矩阵 但我并没有往矩阵上想下去... 这个东西比较显然的是可以把它看成生成函数 然后就可以任意模数fft了 复杂度比题解优 $nlog^2$ t2: 随便推推式子就好了 t3 ...
- lombok @EqualsAndHashCode 注解讲解
官方文档:@EqualsAndHashCode 原文中提到的大致有以下几点: 1. 此注解会生成equals(Object other) 和 hashCode()方法. 2. 它默认使用非静态,非瞬态 ...