线性数据结构---队列,栈 随笔

我们从四个简单但重要的概念开始研究数据结构。栈,队列,deques(双向队列), 列表是一类数据的容器,它们数据元素之间的顺序由添加或删除的顺序决定。一旦一个数据元素被添加,它相对于前后元素一直保持该位置不变。诸如此类的数据结构被称为线性数据结构。

  线性数据结构有两端,有时被称为左右,某些情况被称为前后。你也可以称为顶部和底部,名字都不重要。将两个线性数据结构区分开的方法是添加和移除元素的方式,特别是添加和移除元素的位置。例如一些结构允许从一端添加元素,另一些允许从另一端移除元素。

概念:栈(有时称为“后进先出栈”)是一个元素的有序集合,其中添加移除新元素总发生在同一端。这一端通常称为“顶部”。与顶部对应的端称为“底部”。栈的底部很重要,因为在栈中靠近底部的元素是存储时间最长的。最近添加的元素是最先会被移除的。这种排序原则有时被称为 LIFO,后进先出。它基于在集合内的时间长度做排序。较新的项靠近顶部,较旧的项靠近底部。

  案例:栈的例子很常见。几乎所有的自助餐厅都有一堆托盘或盘子,你从顶部拿一个,就会有一个新的托盘给下一个客人。想象桌上有一堆书, 只有顶部的那本书封面可见,要看到其他书的封面,只有先移除他们上面的书。

栈的分析与应用:

   - 分析:和栈相关的最有用的想法之一来自对它的观察。假设从一个干净的桌面开始,现在把书一本本叠起来,你在构造一个栈。考虑下移除一本书会发生什么。移除的顺序跟刚刚被放置的顺序相反。栈之所以重要是因为它能反转项的顺序。插入跟删除顺序相反。

   - 应用:每个 web 浏览器都有一个返回按钮。当你浏览网页时,这些网页被放置在一个栈中(实际是网页的网址)。你现在查看的网页在顶部,你第一个查看的网页在底部。如果按‘返回’按钮,将按相反的顺序浏览刚才的页面。

Python实现栈

栈的抽象数据类型应该由以下结构和操作定义。栈操作如下: 

  • Stack() 创建一个空的新栈。 它不需要参数,并返回一个空栈。
  • push(item)将一个新项添加到栈的顶部。它需要 item 做参数并不返回任何内容。
  • pop() 从栈中删除顶部项。它不需要参数并返回 item 。栈被修改。
  • peek() 从栈返回顶部项,但不会删除它。不需要参数。 不修改栈。
  • isEmpty() 测试栈是否为空。不需要参数,并返回布尔值。
  • size() 返回栈中的 item 数量。不需要参数,并返回一个整数。

  代码实现:

  Python 中的列表类提供了有序集合机制和一组方法。例如,如果我们有列表 [2,5,3,6,7,4],我们只需要确定列表的哪一端将被认为是栈的顶部。一旦确定,可以使用诸如 append 和 pop 的列表方法来实现操作。

# 创建栈
class Stack():
    def __init__(self):
        self.items = []

    # 入栈(压栈)
    def push(self,item):
        self.items.append(item)

    # 出栈
    def pop(self):
        return self.items.pop()

    # 栈指针回到栈顶部
    def peek(self):
        return len(self.items) - 1

    # 判断栈是否为空,空返回Ture,否则为False
    def isEmpty(self):
        return self.items == []

    # 获取栈长度
    def size(self):
        return len(self.items)

  测试应用:

from basic.stack import Stack

s=Stack()

print(s.isEmpty())
s.push(4)
s.push(‘dog‘)
print(s.peek())
s.push(True)
print(s.size())
print(s.isEmpty())
s.push(8.4)
print(s.pop())
print(s.pop())
print(s.size())

栈的应用实例(URL存放机制)

  模拟网站url地址存放机制:

s = Stack()

# 点击进入一个新的网页
def getRequest(url):
    s.push(url)

# 查看当前网页
def showCurenrUrl():
    print(‘当前页面展示的url:‘+s.pop())

# 回退到前一个网页
def back():
    print(‘回退按钮点击后显示的url:‘,s.pop())

getRequest(‘www.1.com‘)
getRequest(‘www.2.com‘)
getRequest(‘www.3.com‘)

showCurenrUrl()
back()
back()# 结果:>>>
当前页面展示的url:www.3.com
回退按钮点击后显示的url: www.2.com
回退按钮点击后显示的url: www.1.com

双端队列(Deque)

  概念:deque(也称为双端队列)是与队列类似的项的有序集合。它有两个端部,首部和尾部,并且项在集合中保持不变。

  特性:deque 特殊之处在于添加和删除项是非限制性的。可以在前面或后面添加新项。同样,可以从任一端移除现有项。在某种意义上,这种混合线性结构提供了单个数据结构中的栈和队列的所有能力。

  注意:即使 deque 可以拥有栈和队列的许多特性,它不需要由那些数据结构强制的 LIFO 和 FIFO 排序。这取决于你如何持续添加和删除操作。

Python实现Deque

  Deque的抽象数据类型应该由以下结构和操作定义。其中元素可以从首部或尾部的任一端添加和移除。Deque操作如下:

    • Deque() 创建一个空的新 deque。它不需要参数,并返回空的 deque。
    • addFront(item) 将一个新项添加到 deque 的首部。它需要 item 参数 并不返回任何内容。
    • addRear(item) 将一个新项添加到 deque 的尾部。它需要 item 参数并不返回任何内容。
    • removeFront() 从 deque 中删除首项。它不需要参数并返回 item。deque 被修改。
    • removeRear() 从 deque 中删除尾项。它不需要参数并返回 item。deque 被修改。
    • isEmpty() 测试 deque 是否为空。它不需要参数,并返回布尔值。
    • size() 返回 deque 中的项数。它不需要参数,并返回一个整数。

  创建双端队列:

# 创建双端队列
class Dequeue():
    def __init__(self):
        self.items = []

    # 从队列头部插入数据
    def addFont(self,item):
        self.items.insert(0,item)

    # 从队列尾部插入数据
    def addRear(self,item):
        self.items.append(item)

    # 队头取出元素
    def removeFont(self):
        return self.items.pop()

    # 队尾取元素
    def removeRear(self):
        return self.items.pop(0)

    # 获取队列长度
    def size(self):
        return len(self.items)

  队列测试:

q = Dequeue()
q.addFont(1)
q.addFont(2)
q.addFont(3)

# print(q.removeFont())
# print(q.removeFont())
# print(q.removeFont())
print(q.removeRear())
print(q.removeRear())
print(q.removeRear())

# 结果>>>
3
2
1

双端队列的应用案例(回文检查)

  回文检测:设计程序,检测一个字符串是否为回文。

  回文:回文是一个字符串,读取首尾相同的字符,例如,radar toot madam

  分析:该问题的解决方案将使用 deque 来存储字符串的字符。我们从左到右处理字符串,并将每个字符添加到 deque 的尾部。在这一点上,deque 像一个普通的队列。然而,我们现在可以利用 deque 的双重功能。 deque 的首部保存字符串的第一个字符,deque 的尾部保存最后一个字符。我们可以直接删除并比较首尾字符,只有当它们匹配时才继续。如果可以持续匹配首尾字符,我们最终要么用完字符,要么留出大小为 1 的deque,取决于原始字符串的长度是偶数还是奇数。在任一情况下,字符串都是回文。

class Dequeue():
    def __init__(self):
        self.items = []

    def addFront(self,item):
        self.items.insert(0,item)

    def addRear(self,item):
        self.items.append(item)

    def removeFront(self):
        return self.items.pop()
    def removeRear(self):
        return self.items.pop(0)

    def size(self):
        return len(self.items)

def isHuiWen(s):
    de = Dequeue()
    ex = True
    for sr in s:
        de.addFront(sr)

    while de.size() > 1:
        if de.removeFront() != de.removeRear():
            ex = False
            break

    return ex

print(isHuiWen("abcba"))

队列的应用实例(烫手的山芋)

  实验规则:烫手山芋游戏介绍:6个孩子围城一个圈,排列顺序孩子们自己指定。第一个孩子手里有一个烫手的山芋,需要在计时器计时1秒后将山芋传递给下一个孩子,依次类推。规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏。该游戏直到剩下一个孩子时结束,最后剩下的孩子获胜。请使用队列实现该游戏策略,排在第几个位置最终会获胜。

  分析:

  • 为了模拟这个圈,我们可以使用队列。假设游戏开始时,排在队列中的第一个(队首)的孩子手里拿着山芋。游戏开始后,拿着山芋的孩子出队列然后再入队列,将山芋传递给下一个孩子。每当山芋到队首孩子手里后,队首的孩子先出队列再入队列,依次类推。当传递六次后,手里有山芋的孩子淘汰,游戏继续,继续传递山芋。
  • 手里有山芋的孩子淘汰后,队列指针指向下一个孩子,保证手里有山芋的孩子永远站在队列的头部

  代码实现:

q = Queue()
kids = [‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘]

# 进队列(循环队列)
for kid in kids:
    q.enqueue(kid)

# 队列中剩最后一个孩子则跳出循环,孩子获胜
while q.size() > 1:
    # 内层循环是用来将手里有山芋的孩子排在队头
    # 每次计时器到时,删除当前孩子,则指针指向的下一个孩子位置
    # 每次计时,循环队列
    for i in range(6):
        # 删除队列最后一个孩子
        kid = q.dequeue()
        # 删除的孩子重新添加在队首位置,实现队列循环
        q.enqueue(kid)
    # 6s计时到时,删除最后一个孩子,指针指向下一个孩子
    q.dequeue()

# 打印最后获胜的孩子
print(q.dequeue())

# 孩子E获胜,留下的最后一个孩子
# 结果>>>E

Python实现队列

  队列的抽象数据类型应该由以下结构和操作定义。队列操作如下:

    • Queue() 创建一个空的新队列。 它不需要参数,并返回一个空队列。
    • enqueue(item) 将新项添加到队尾。 它需要 item 作为参数,并不返回任何内容。
    • dequeue() 从队首移除项。它不需要参数并返回 item。 队列被修改。
    • isEmpty() 查看队列是否为空。它不需要参数,并返回布尔值。
    • size() 返回队列中的项数。它不需要参数,并返回一个整数。


class Queue():
    def __init__(self):
        self.items = []

    # 队列插入元素(左端)
    def enqueue(self,item):
        self.items.insert(0,item)

    # 队列删除元素(右端)
    def dequeue(self):
        return self.items.pop()

    # 判断队列是否为空,空返回True,否则返回False
    def isEmpty(self):
        return self.items == []

    # 返回队列长度
    def size(self):
        return len(self.items)

  队列测试:

>>> q.size()
3
>>> q.isEmpty()
False
>>> q.enqueue(8.4)
>>> q.dequeue()
4
>>> q.dequeue()
‘dog‘
>>> q.size()
2

原文地址:https://www.cnblogs.com/anthony-wang0228/p/11524197.html

时间: 2024-10-14 13:44:22

线性数据结构---队列,栈 随笔的相关文章

线性数据结构——队列

上次说了,一头进一头出的就是栈,那么什么是队列(queue)呢,就是一头进另一头出.正如我们排队一样,来了人只能站在队尾,先走的人只能是队头.在队列中,总是遵循fifo,fist in first out. 队列通常分为以下几种:顺序队列和循环队列还有链队列.本文主要讲循环队列 顺序队列 这个就不再这里过多叙述了,通常采用连续的数据空间存储队列中的元素,就像这样子 其中front表示队头,near表示队尾 循环队列 顺序队列当队头不断地被取出,front会不断的往后移,这时候就会造成内存的极大浪

数据结构之栈定义及基本操作实现

终于有可以有时间写点数据结构的学习总结了,前段时间一直在紧张的忙一些项目,都没有空出时间来学习数据结构,现在终于可以稍微喘口气了,还是数据结构有意思,这两天看了点栈的东西,写下来总结一下,有错误的地方希望看到的朋友指出来,感激不尽. 根据学习,栈就是一种线性数据结构,栈的运算只能在表的一段进行,所以这种数据结构具有“后进先出”的特点. 接下来是栈的c语言实现.其中栈由一个top节点和bottom节点组成,这两个节点分别指向栈的顶部和底部.其中栈的组成结点是由结构体实现,结构体由数据库和指向下一个

数据结构之栈的简单应用(判断字符串中括号的合法性)

数据结构之栈(判断字符串中括号的合法性) 栈的定义 栈是一种线性数据结构,栈的特征是数据的插入和删除只能通过一端来实现,这一端称为"栈顶",相应的另一端称为"栈底":另外其还有先进后出,后进先出的特征. 栈是一种高效的数据结构,因为数据只能在栈的顶端添加或者删除,所以这样的操作很快而且容易实现. 说到线性结构,得先了解一下数据的逻辑结构,数据的逻辑结构分为线性结构.集合结构.树形结构和图形结构,如下图所示,栈是一种特殊的线性表,是线性结构的一种. JavaScrip

数据结构回顾之顺序存储结构中的线性表(栈与队列顺序线性表实现)

说到数据结构呢,对于一个Coder来说还是蛮重要的啦,每次看数据结构的东西都有新的收获,这两天在回顾数据结构的知识.当然啦,虽然数据结构有些是理论的东西,如果好好的理解数据结构的东西还是少不了的代码的支撑的.数据结构简单的来说吧,可以分为两大类,一个是数据的"物理存储结构",另一种是数据的"逻辑存储结构".数据的"物理存储结构"又可分为顺序的和链式的(下面将会结合着代码打印内存地址的形式来观察物理存储结构). 逻辑存储结构又可分为集合,线性, 树

数据结构学习笔记(特殊的线性表:栈与队列)

栈与队列 栈是限定仅在表尾(栈顶)进行插入和删除操作的线性表(后进先出).队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表(先进先出). 栈(Stack): 1.下标为0的一端作为栈底比较好,因为首元素都存在栈底,变化最小,所以让它作为栈底.定义一个top变量来指示栈顶元素在数组中的位置.栈顶位置top必须小于存储栈长度StackSize,把空栈的判定条件定位top等于-1. 2.进栈与出栈操作(顺序存储结构): 进栈操作push:/*插入元素e为新的栈顶元素*/Status Pu

数据结构之栈和队列

数据结构学习继续向前推进,之前对线性表进行了学习,现在我们进入栈和队列的学习.同样我们先学习一些基本概念以及堆栈的ADT. 栈和队列是两种中重要的线性结构.从数据结构角度看,栈和队列也是线性表,只不过是受限的线性表.因此可以称为限定性数据结构.但从数据类型来看,他们是和线性表大不相同的两类重要的抽象数据类型. 栈:(stack)是限定仅在表尾进行相应插入和删除操作的线性表.因此,对栈来说,表尾有其特殊含义,称为栈顶,表头称为栈底,不含元素的空表称为空栈.栈一个重要特性就是后进先出.OK,我们来看

<2014 05 16> 线性表、栈与队列——一个环形队列的C语言实现

栈与队列都是具有特殊存取方式的线性表,栈属于先进后出(FILO),而队列则是先进先出(FIFO).栈能够将递归问题转化为非递归问题,这是它的一个重要特性.除了FILO.FIFO这样的最普遍存取方式外,还有一些扩展的数据结构,如双端队列.双栈.超队列.超栈等,它们是一种扩展与变异结构. 线性表有顺序存储和链接存储两类,这是针对计算机的线性存储空间作出的分类.前者可以是数组,后者可以是链表.字符串是线性表最常见的应用. 这里我用C语言实现了一个基于数组环形队列,它具有固定的队列空间.相比于链表实现,

Learning Data Structure_2_线性表、栈和队列

一个人在学校的日子有些寂寞,但是st说男人要耐得住寂寞,做学问也是如此吧.今天看了线性表.栈和队列的内容.以下是学习记录. 线性表(list) 1.定义:0个或多个数据元素的有限序列,元素有且只有一个直接后继和一个直接前驱:基本操作ListLength.GetElem.LocateElem.ListInsert等,并集Union的实现. 2.线性表的顺序存储结构 指用一段地址连续的存储单元依次存储数据元素(c语言中用数组实现改结构):数组长度>=线性表的长度:对于任意位置的存入或取出的所需时间相

【数据结构】栈和队列

栈和队列 容器数据结构是指一些包含了若干个其他相同或不同的数据结构的数据结构,被包含的这些每一个独立的数据结构都被称为一个元素,在一个容器中的元素往往支持相同的操作,具有类似的性质.之前说到过的线性表其实就是一种容器数据结构,本文中介绍的两种最常用的容器数据结构是栈和队列. 从功能上看,栈和队列大多用于计算过程中保存临时数据,这些数据是在计算过程中发现或产生的.在而后的计算中可能会用到这些数据.如果这些数据是固定的个数以及大小的话,可以构建几个变量来储存它们,但是如果这些数据不确定的话,就需要一