1.3 队列

1.3.1 队列的数据类型

队列当中没有位置的概念,只要求保证先进先出即可。

1.3.2 队列的数据操作

1.3.2 队列的实现(主要基于线性表的技术)

1.3.2.1 基于链表的实现代码(由于队列实质上是线性表约束下的结构,所以只需要在线性表的基础上修改)
# 链表的基础上实现队列
class Lnote():
    def __init__(self,ele=None,next_=None):
        self._element=ele
        self._next = next_

class Llist():
    def __init__(self):
        self._head = None
    def preappend(self,ele):  # 于表头添加元素
        self._head = Lnote(ele,self._head)

    def out_me(self):   # 于表尾弹出元素
        p = self._head
        if p == None:
            print('队列里无元素')
        elif p._next == None:
            print(p._element)
            self._head=None
        else:
            while p._next is not None:
                p0=p
                p = p._next
            print(p._element)
            p0._next = None    # 记住一定是改指针p的next而非直接给节点赋值为None
1.3.2.2 基于顺序表的固定容量的队列实现代码

这里需要说明的是:

  • 利用list为基础构造的队列,固定循环长度是必要的。有两种循环的方法,①指针到了最末端,指定回到0②用p%len.也可以优雅的循环指针。这里采取了前者。
  • 在队头指针与队尾指针相等时,队列为空,当队尾+1刚好等于队头时,队列为满。
  • 用指针为引索,给定义好的列表赋值。
# 顺序表实现固定容量的队列结构
class Queuelist():
    
    def __init__(self,max_len=6): 
        self._inpoint = -1
        self._outpoint = -1
        self._Queue = list(range(max_len))
        self._max_len = max_len
                           
    def inqueue(self,x):
        if self._inpoint ==self._max_len-2:
            self._inpoint = -2
        if (self._inpoint +1)==self._outpoint:
            raise Exception("队列已满!!!")
        if self._inpoint == -2:
            self._inpoint=-1
        self._inpoint += 1
        self._Queue[self._inpoint]=x
        
    def outqueue(self):
        if not self._inpoint==self._outpoint:
            if self._outpoint ==self._max_len-2:
                self._outpoint = -2
            if self._inpoint == -2:
                self._inpoint=-1
            self._outpoint += 1
            if self._outpoint == -1:
                print('队列为空')
            else:
                return self._Queue[self._outpoint]
        else:
            print("队列为空,无法出队")
        
    def is_full(self):
        return (self._inpoint+1)==self._outpoint
    
    def is_empty(self):
        return self._inpoint==self._outpoin
1.3.2.3 基于list的无限容量队列的实现代码
设计并实现:
  • 由于list的自动扩容机制和队列的扩容机制不一致,所以必须设计队列独有的扩容机制
  • 会定义新的异常类
  • 考虑到    SQueue类里面必须有的变量: _head(队首位置),_elements(元素),_nums(元素个数),_len(list的长度)。 
  • 数据不变式的概念:类里面的各种属性之间的相互平衡,每个属性的变化所牵涉到的另一个属性的变化规则。只有遵从这里面的关系,才能保证类在操作过程中不会出现问题。满足数据不变式要做到两点,① 初始状态的属性满足 ② 类的操作之后不会破坏。
那么,现在我们考虑设计一个队列的数据不变式的逻辑:
  • _head :队首元素的下标,当出队的时候,它的值必然改变
  • _nums:队列的元素个数,它实实在在记录着队列中的元素个数,添加队尾元素需要用head+nums确定下标
  • _element:定义了不需要扩容时存放的list容器
  • _len:记录elements的长度,当len==nums的时候表明,容器满,需扩容

具体实现代码:

class SQueue():
    
    def __init__(self, len_=8):
        self._head = 0  # 队首下标
        self._len = len_ # 存储区长度
        self._elements = [0]*self._len # 元素s
        self._nums = 0  # 队列元素个数
        
    def is_empty(self):
        return self._nums == 0

    def peek(self):  # 查看队首元素
        if self._nums == 0:
            return print('队列为空')
        else:
            return self._elements[self._head]

    def dequeue(self):  # 出队
        if self._nums == 0:
            return print('队列为空,无法出队')
        out_id = self._head
        self._head  += 1
        self._nums  -= 1
        return self._elements[out_id]

    def enqueue(self,x):
        if self._nums==self._len:
            self.extent()
        self._elements[(self._head+self._nums)%self._len] = x # 这一个取余数的操作是妙极了
        self._nums += 1

    def extent(self): # 扩容
        old_len = self._len
        self._len *= 2
        new_elements =[0]*self._len
        # 将可能折叠的状态理顺放入新的存储区
        for i in range(old_len):
            new_elements[i]= self._elements[(self._head+i)%old_len]
        self._elements = new_elements
        self._head = 0
  • 上面的代码有两个地方十分关键:① 很好的保证了数据不变式的关系,使得每一个操作都显得十分和谐 ② (head+nums)

%len 的循环模式 ③ 变存储区的元素对应关系的处理

猜你喜欢

转载自blog.csdn.net/tommy1295/article/details/80789122
1.3