栈和队列

1.   栈和队列

保存临时数据(缓存)

只支持数据项的存储和访问,不支持数据项之间的任何关系

线性表作为栈和队列的实现结构

栈:先进后出(取碗)                   队列:先进先出(排队)

 

2.   栈

存入,访问,删除元素

任何时候可以访问,删除的元素都是最后一个元素

存储方式(2种):顺序栈,链栈

入栈:插入元素

出栈:删除元素

2.1    顺序栈

使用顺序表作为存储结构,利用一组地址连续的存储单元依次自栈底到栈顶的元素,附设top指示栈顶。顺序表的后端插入和删除为 O(1),使用表尾作为栈顶。

 

 

<-- 栈顶(top)

E

 

D

 

C

 

B

 

A

<-- 栈底(base)

1.      #顺序栈的实现,利用list存储栈的元素

class StackUnderflow(ValueError):

   pass

 

class SStack():

   def __init__(self):

       self._elem = []      #所有栈操作都映射到list

       

   def is_empty(self):

       return self._elem == []

       

   def top(self):

       #查看栈顶元素

       if self._elem == []:

           raise(StackUnderflow('in SStack.pop()'))

       else:

           return self._elem[-1]

 

   def push(self,data):

       #入栈

       self._elem.append(data)

       

   def pop(self):

       #出栈

       if self._elem == []:

           raise(StackUnderflow('in SStack.pop()'))

       else:

           return self._elem.pop()     #调用自带的pop方法

 

a = SStack()

a.push(1)

a.push(2)

a.top()

a.pop

print(a.pop())

 

 

3. 队列

队列:先进先出的线性表

它只允许在表的一端插入,而在另一端删除

 

出队 <--

A1    A2

  …..

An

<--入队

 

|

队头

 

|

队尾

 

 

双端队列:限定插入和删除操作在表的两端进行的线性表,实际应用较少

3.1 链队列

链队列:使用链表表示的队列(队列也要2种储方式),需要两个指针(指向队头和队尾指针)才能惟一确定。链队列为空的条件是头指针和尾指针均指向头结点。

#链队列

class Node(object):

   def __init__(self,elem,next_=None):

       self.elem = elem

       self.next = next_

       
class LQueue(object):

   def __init__(self):

       self._front = None

       self._rear = None
  
   def is_empty(self):

       return self._front is None

   
   def peek(self):

        #查看队头

       if self.is_empty():

           print('queue is empty')

       return self._front.elem

   
   def dequeue(self):

       #出队

       if self.is_empty():

           print('queue is empty')

       e = self._front.elem

       self._front = self._front.next

       return e

       
   def enqueue(self,e):

       #入队

       p = Node(e)

       if self.is_empty():

           self._front = p

           self._rear = p

       else:

           self._rear.next = p

           self._rear = p

 
a = LQueue()
print(a.is_empty())
a.enqueue(1)
a.enqueue(2)
a.enqueue(3)
print(a.peek())
a.dequeue()
print(a.peek())

 

3.1 队列的顺序表示与实现

队列头指针:front   尾指针:rear

 

循环队列:    队空:front =rear

                             队满:(1)设置标志位

                                       (2)头指针在尾指针的下一位:front==(rear+1)%max_size

                                                        将在表里留下一个不用的空位

 

 

实现:

#思路:基于循环顺序表实现的

#使用固定大小的list实现

#_elem:队列的元素存储区

#_head:队列首元素

#_len:存储区有效容量

#新入队的元素位置:_head+_num

#_num=_len:队列已满,若出现入队操作,扩大内存区

#_num = 0:队列空

 

class QueueUnderflow(ValueError):

   pass

 
class SQueue():

   def __init__(self,init_len=4):

       self._len = init_len                #存储区长度

       self._elem = [0]*init_len           #元素存储

       self._head = 0                     #表头元素下标

       self._num = 0                      #元素个数       

   def is_empty(self):

        return self._num == 0  

   def peek(self):

       #查看队头元素

       if self._num == 0 :

           raise QueueUnderflow

       return self._elem[self._head]

   def dequeue(self):

       #出队

       if self._num == 0:

           raise QueueUnderflow

       e = self._elem[self._head]             #取出队头并返回

       self._head = (self._head+1)%self._len  #头指针指向新的队头

       self._num -= 1                         #队列元素数量减1

       return e

   
   def enqueue(self,e):

       #入队

       if self._num == self._len:

           self.__extend()

       self._elem[(self._head+self._num)%self._len] = e

       self._num += 1       

   def __extend(self):

       #队列满时扩大内存

       old_len = self._len

       self._len = 2*old_len

       new_elem = [0]*self._len

       for i in range(old_len):

           new_elem[i] = self._elem[(self._head+i)%old_len]

       self._elem,self._head = new_elem, 0
    

sq = SQueue()
sq.enqueue(1)
sq.enqueue(2)
sq.enqueue(3)
sq.enqueue(4)
sq.enqueue(5)
print(sq.peek())
print(sq.dequeue())
print(sq.peek())

 

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值