数据结构与算法(六)-背包、栈和队列

 前言:许多基础数据类型都和对象的集合有关。具体来说,数据类型的值就是一组对象的集合,所有操作都是关于添加、删除或是访问集合中的对象。而且有很多高级数据结构都是以这样的结构为基石创造出来的,在本文中,我们将了解学习三种这样的数据类型,分别是背包(Bag)、栈(Stack)和队列(Queue)

一、学习感悟

  对于数据结构的学习可以用以下步骤来学习:
  • 首先先对该结构的场景操作进行API化;
  • 然后再对数据类型的值的所有可能的表示方法以及各种操作的实现;
  • 总结特点和比较;
  接下来就对这三种数据类型进行介绍。

二、API

  这三种数据类型都是依赖于之前介绍过的线性表的链式存储结构的,所以理解并掌握链式结构是学习各种算法和数据结构的第一步,若还不是很清楚,可以看一下前面关于线性表的链式存储结构的文章(本文主要是对链式存储结构的进行介绍,如想要对顺序存储结构了解的话,可根据其特性和API进行编写代码,欢迎在评论区留言讨论)。

2.1、背包(Bag)

  背包是一种不支持从中删除元素的集合数据类型——它的目的就是帮助用例收集元素并迭代遍历所有收集到的元素(用例也可以检查背包是否为空或者获取背包中元素的数量)。
  要理解背包的概念,可以想象一个喜欢收集弹珠球的人。他将所有的弹珠球都放在一个背包里,一次一个,并且会不时在所有的弹珠球中寻找某一颗;
  

 

2.1.1 背包API

  根据以上的需求,可以写出背包的API:
复制代码
public class Bag<Item> implements Iterable<Item>   Bag()                    创建一个空背包   void add(Item item)      添加一个元素   boolean isEmpty()        背包是否为空   int size()               背包中的元素数量          
复制代码
  使用Bag的API,用例可以将元素添加进背包并根据需要随时使用foreach语句访问所有的元素。用例也可以使用栈或是队列,但是用Bag可以说明元素的处理顺序不重要,比如在计算一堆Double值的平均值时,无需关注背包元素相加的顺序,只需要在得到所有值的和后除以Bag中元素的数量即可。

2.1.2 背包实现

  根据2.1.1的API写出具体的实现,其中关键方法add使用了头插法:
 Bag.java

  核心代码为add(),使用了头插法::

复制代码
    //由于Bag类型不需要考虑元素的相对顺序,所以这里我们可以使用头插法来进行插入,提高效率    public void add(T t) {         Node<T> newNode = new Node<>();         newNode.t = t;         newNode.next = first.next;         first.next = newNode;         size++;     }
复制代码

2.1.3 总结

  上面就是关于Bag数据类型的实现,从中可以看出Bag是一种不支持删除元素的、无序的、专注于取和存的集合类型。

2.2、栈(Stack)

  下压栈(或简称栈)是一种基于后进先出(LIFO)策略的集合类型。比如在桌子上对方一叠书,我们拿书时,一般都是从最上面开始取的,这样的操作就类似栈。
  

 

  栈管理数据的两种操作如下:
  • 写入数据(堆积)操作称作入栈(PUSH);
  • 读取数据操作称作出栈(POP);
  栈类型的模型结构在生活中的应用也不少,比如浏览器的回退功能,在一个浏览器tag页上打开的网页,通过回退功能可以一次回退到历史最近的浏览记录。还有电脑软件撤销功能,也是这样的策略模型。
  栈是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一段被称为栈顶,相对的,把另一端称为
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信