Bootstrap

python数据结构之栈和队列

python数据结构之栈和队列

3.1栈

3.1.1栈的定义

特点:

  • 后进先出,先进后出
  • 允许插入、删除的一端为栈顶,另一端为栈底
  • 无元素为空栈
  • 插入操作称为进栈或如栈,删除操作称为退栈或出栈

基本运算
empty():判断是否为空
push(e):将元素e插入作为栈顶元素
pop():出栈,返回栈顶元素
gettop():返回当前栈顶元素

3.1.2栈的顺序存储结构及其基本运算算法的实现
  1. 顺序存储结构
    用列表data存放栈中元素,称为顺序栈,data[0]端为栈底,data[-1]端为栈顶,len(data)为栈中实际的元素个数
元素索引01……i……n-1
data列表a0a1……a i……an-1
		           栈底			                      top⬆️ 
  1. 顺序栈四要素
  • 栈空:len(data)==o或者not data
  • 栈满:不考虑
  • 元素e进栈:将e加到栈顶
  • 出栈:删除栈顶元素,返回该元素
  1. 顺序栈基本运算

#初始化
class SqStack:
    def __init__(self):
        self.data=[]

#判断栈是否为空
    def empty(self):
        if len(self.data)==0:
            return True
        return False

#进栈
    def push(self,e):
        self.data.append(e)

#出栈
    def pop(self):
        assert not self.empty()
        return self.data.pop()

#取栈顶元素
    def gettop(self):
        assert not self.empty()
        return self.data[-1]

3.1.3栈的链式存储结构
  1. 特点:
  • 首结点是栈顶结点,尾结点是栈底结点
  1. 四要素:
  • 栈空:head.next==None
  • 栈满:不考虑
  • 元素e进栈:将包含该元素的结点s插入,作为首结点
  • 出栈:返回首结点值,并删除该结点
  1. 链栈基本运算

#初始化
class LinkNode():
    def __init__(self,data=None):
        self.data=data
        self.next=None

class LinkList():
    def __init__(self):
        self.head=LinkNode()
        self.head.next=None
#判断是否为空
    def empty(self):
        if self.head.next==None:
            return True
        return False
#进栈
    def push(self,e):
        p=LinkNode(e)
        p.next=self.head.next
        self.head.next=p
#出栈
    def pop(self):
        assert self.head.next!=None
        p=self.head.next
        self.head.next=p.next
        return p.data
#取栈顶元素
    def gettop(self):
        assert self.head.next!=None
        return self.head.next.data

3.2队列

3.2.1队列的定义

特点:

  • 插入的一端称为队尾,进行删除的一端为队头或队首
  • 插入新元素为进队或入队,新元素进队后就成为新的队尾元素
  • 从队列删除元素为出队或离队,出队后其后继元素为新的队首元素
  • 队列也称为先进先出表
    基本运算
    empty():判断是否为空 push(E e):进队,将元素e插入作为队尾元素 pop():出队,从队头出队第一个元素 gethead():取队头,返回队头元素的值而不出队`
3.2.2队列的顺序存储结构及其基本运算算法的实现
  1. 顺序存储结构——顺序队
    front:队头元素的前一个位置
    rear:队尾元素的位置
数组下标0…………MaxSize-1
data数组a0……a i……an-1
                      ⬆️ 						   ⬆️
	                 front	 					  rear 
  1. 非循环队列
  • 四要素:
  • 队空条件:front==rear
  • 队满条件:rear==MaxSize-1
  • 元素e进队操作:队尾指针rear+1,然后将e放在该位置
  • 出队操作:front+1,然后取出该位置的元素
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 基本运算

#初始化
MaxSize=100
class SqQueue:
    def __init__(self):
        self.data=[None]*MaxSize
        self.front=-1
        self.rear=-1

#判断是否为空
    def empty(self):
        return self.front==self.rear
#进队
    def push(self,e):
        assert not self.front==self.rear
        self.rear+=1
        self.data[self.rear]=e
#出队
    def pop(self):
        assert not self.empty()
        self.front+=1
        return self.data[self.front]
#取队头元素
    def gethead(self):
        assert not self.empty()
        return self.data[self.front+1]

  1. 循环队列
  • 特点:
  • 队首指针循环进1,front=(front+1)%MaxSize
  • 队尾指针循环进1,rear=(rear+1)%MaxSize
  • 循环队列的队首与队尾指针初始化均为0,即front=rear=0
  • 四要素:
  • 队空条件:front==rear
  • 队满条件:(rear+1)%MaxSize==front
  • 元素e进队操作:rear=(rear+1)%MaxSize
  • 出队操作:front=(front+1)%MaxSize
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#初始化
MaxSize=100
class CSqQueue:
    def __init__(self):
        self.data=[None]*MaxSize
        self.front=0
        self.rear=0
#判断是否为空
    def empty(self):
        return self.front==self.rear
#进队
    def push(self,e):
        assert (self.rear+1)%MaxSize!=self.front
        self.rear=(self.rear+1)%MaxSize
        self.data[self.rear]=e
#出队
    def pop(self):
        assert not self.empty()
        self.front=(self.front+1)%MaxSize
        return self.data[self.front]
#取队头元素
    def gethead(self):
        assert not self.empty()
        head=(self.front+1)%MaxSize
        return self.data[head]

3.2.3队列的链式存储结构

  1. 特点
  • 这里的单链表不带头结点
  • 使用两个指针标识,front指向队头结点,rear指向队尾结点
  • 用来存储单链表的的队列为链队
  1. 四要素
  • 栈空:front=rear=None,可以仅以front=None表示
  • 栈满:不考虑
  • 元素e进队:将包含该元素的结点s插入到单链表尾部,并让队尾指针指向它
  • 出队:取出队首结点的data值并将其从链队中删除
  1. 基本运算

#初始化
class LinkNode():
    def __init__(self,data=None):
        self.data=data
        self.next=next
class LinkQueue():
    def __init__(self):
        self.front=None
        self.rear=None    
#判断是否为空
    def empty(self):
        return self.front==None
#进队
    def push(self,e):
        s=LinkNode(e)
        if self.empty():
            self.front=self.rear=s
        else:
            self.rear.next=s
            self.rear=s
#出队
    def pop(self):
        assert not self.empty()
        if self.front==self.rear:
            e=self.front.data
            self.front=self.rear=None
        else:
            e=self.front.data
            self.front=self.front.next
        return e
#取队头元素
    def gethead(self):
        assert not self.empty()
        e=self.front.data
        return e

3.2.4 双端队列

  1. 特点
  • 可以在两段进行进队和出队,具有队列和栈的特性
  • double-ended queue简称deque,在collections集合里
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  1. 创建双端队列
  • 创建一个空双端队列qu=deque()
  • 创建一个固定长度的双端队列qu=deque(maxlen=N),此时qu为空,固定长度为N,当新的元素加入而双端队列满时,自动删除最老的元素
  • 由一个列表元素创建一个双端队列qu=deque(L),此时qu包含列表L中的元素
  1. 双端队列的方法
    deque.clear():清除所有元素
    deque.append(x):在队列右端添加x,时间复杂度O(1)
    deque.appendleft(x):在队列左端添加x,时间复杂度O(1)
    deque.pop():在队列右端出队一个元素,时间复杂度O(1)
    deque.popleft():在队列左端出队一个元素,时间复杂度O(1)
    deque.remove(x):在队列中删除首个和x匹配的元素,时间复杂度O(n)
    deque.count(x):计算队列中元素为x的个数,时间复杂度O(n)
    deque.extend(L):在队列右端添加列表L的元素
    deque.entendleft(L):在队列左端添加列表L的元素
    deque.reverse():逆置列表中所有元素
    deque.rotate(n):移位,n为正,向右移,n为负,向左移

  2. 用双端队列实现栈

  • 方法1:左端为栈底,右端为栈顶,append()为进栈方法,pop()为出栈方法
  • 方法2: 左端为栈顶,右端为栈底,appendleft()为进栈方法,popleft()为出栈方法
例:

from collections import deque
st=deque()
st.append(1)
st.append(2)
st.append(3)
while len(st)>0:
    print(st.pop(),end='')
print()
  1. 用双端队列实现普通队列
  • 左端为队头(出队端),右端为队尾(进队端),用popleft()作为出队方法,append()作为进队方法
  • 右端为队头(出队端),左端为队尾(进队端),用pop()作为出队方法,appendleft()作为进队方法
例:

from collections import deque
qu=deque()
qu.append(1)
qu.append(2)
qu.append(3)
while len(qu)>0:
    print(qu.popleft(),end='')
print()

;