栈是一种重要的线性结构。栈是线性表的一种具体的形式。

栈的官方定义:栈是一个后进先出的线性表,它要求只在表尾进行删除和插入操作。

表尾称为栈的栈顶(top),表底部称为栈的栈底(bottom),栈的插入操作(push)叫压栈或入栈,栈的删除操作(pop)叫做出栈,也叫作弹栈。

栈并不是python的内建类型,程序员可以使用列表结构来实现栈的功能。j

栈的实现:

class Stack:
    def __init__(self):
        self.stack=[]
    def isEmpty(self):
        """
        栈的清空
        :return:
        """
        self.stack.clear()
        return self.stack

    def push(self,item):
        """
        栈的压入
        :param item:
        :return:
        """
        self.stack.append(item)

    def pop(self):
        """
        出栈
        :return:
        """
        if self.isEmpty():
            raise IndexError('pop from empty stack')
        return self.stack.pop()
    def peek(self):
        """
        返回栈顶数据
        :return:
        """
        return self.stack[-1]
    def size(self):
        """
        返回当前栈的大小
        :return:
        """
        return len(self.stack)


a=Stack()

a.push(5)
a.push(6)
a.push(7)
print(a.peek())
print(a.size())
栈的实现

结果

7
3

栈的应用:

1.维护web游览器所访问过的链接的历史记录。

2. 括号 匹配问题:给一个字符串,字符串中有小括号,中括号大括号,求该字符串中的括号是否匹配,实例‘({[]})’

解题思路: 做一个空栈,把字符串中的左括号先push栈中,右括号匹配左括号,如果匹配上就出栈,直到栈和字符串中没有括号为止,即为成功匹配

##'([{}])'

def kuohao(s):
    stack=[]
    for i in s:
        if i in ['(','[','{']:
            stack.append(i)
        elif i==')':
            if len(stack)>0 and stack[-1]=='(': #匹配上则出栈
                stack.pop()
            else:
                return False
        elif i == ']':
            if len(stack) > 0 and stack[-1] == '[':
                stack.pop()
            else:
                return False
        elif i == '}':
            if len(stack) > 0 and stack[-1] == '{':
                stack.pop()
            else:
                return False
    if len(stack)==0:   #最后查看栈中还有没有左括号,没有即为完全匹配
        return True
    else:
        return False
括号匹配代码

 

3.十进制转2进制

def tentotwo(num):
    stack=[]
    stack2=[]
    while num >0 :
        set=num %2 #区余数
        num=num//2
        stack.append(set)
    while len(stack)>0:
        stack2.append(stack.pop()) #倒着push到stack2中
    return stack2

print(tentotwo(100))

 

结果:

[1, 1, 0, 0, 1, 0, 0]

 

4. Flask中的上下文管理中把请求上下文对象和应用上下文对象放到local对象中,就是应用了栈

 

队列(queue)

队列(queue):是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出的线性表

队列既可以用链表实现,也可以用数组来实现。

栈一般我们用顺序表来实现,而队列我们常用链表来实现,简称为链队列。

队列不能用列表来实现,当队首删除的时候所有的元素都要移动一个位置。时间复杂操作为o(n)。

在python中提供队列功能的模块叫:

from collections import deque

链表队列实现:

我们定义如下的链表来实现队列数据结构:

定义一个头节点,左边指向队列的开头,右边指向队列的末尾,这样就可以保证我们插入一个元素和取出一个元素都是O(1)的操作,使用这种链表实现stack也是非常的方便。实现代码如下:

 

class Node:
    """
    节点类
    """
    def __init__(self,item):
        self.item=item
        self.next=None

class Head:
    """
    头节点类
    """
    def __init__(self):
        self.right=None
        self.left=None


class LinkQueue:
    """
    链表队列类
    """
    def __init__(self):
        self.head=Head()
        self.size=0

    def add(self,item):
        """
        队列添加函数
        :param item: 
        :return: 
        """
        newNode=Node(item)
        if self.head.right: #如果head节点的右边不为空,说明队列中已经有值了。取出head节点右边指向的那个节点
            temp=self.head.right#取出当前队列的最后一个节点
            self.head.right=newNode#把head节点的right指向新节点
            temp.next=newNode #把当前队列的最后一个节点的next指向新节点
            self.size+=1
        else:
            self.head.left=newNode
            self.head.right=newNode
            self.size += 1

    def pop(self):
        """
        队列删除函数
        :return: 
        """
        if self.head.right:
            if self.head.right==self.head.left:#说名只有一个节点
                tep=self.head.left
                self.head.left=self.head.right=None
                self.size=0
                return tep.item
            else:
                t1=self.head.left  #把要删除的值先取出来
                self.head.left=t1.next  #把head。left连接上第二个节点
                self.size-=1
                return t1.item

        else:
            raise LookupError('列表为空')

    def peek(self):

        """
        #查询队列的第一个值
        :return:
        """
        if self.head.left:
            return self.head.left.item
        else:
            raise LookupError('列表为空')

    def size(self):
        """
        查询队列的元素个数
        :return: 
        """
        return self.size


q=LinkQueue()
q.add(5)
q.add(6)
q.add(7)

# print(q.pop())
# print(q.pop())

print(q.size)
链表队列

循环队列实现

队列不能用列表来实现,当队首删除的时候所有的元素都要移动一个位置。时间复杂操作为o(n)。

我们可不可以这样当删除操作队首元素时,只是队首位置向后移动了一个,其他位置不变,这样不就解决了,所有元素都要移动一个位置的问题吗? 但是,我们会发现,队列的实际空间变小了一个,这就是队列的假溢出。

怎么解决这个问题呢?

解决的办法是,如果队列满了,就从队列的头开始也就是头尾相接的循环,就用到了循环队列

我们定义一个头节点,有front 变量指向第一个节点,rear变量指向最后一个节点,当pop操作时front变量指向下一个节点,其他节点不动,当add操作时,rail变量指向新添加的节点,知道队列没有空余空间为止。

也就是在add和pop操作中front和rail变量的索引不断加1,但是如何让rail和front操作队列最大的索引呢即溢出,我们可以采取取模的方式,rail的值就等于(rail+1)//队列容量    ,front=(front+1)%队列容量,

这样rail和front永远不会溢出。

 

posted on 2018-11-22 21:29  程序员一学徒  阅读(165)  评论(0)    收藏  举报