python实现可扩容队列

#coding:utf-8
"""
fzh created on 2019/10/15
构建一个队列
"""
import datetime


class LoopQueue(object):
    def __init__(self, n=10):
        self.arr = [None] * (n+1)  # 由于特意浪费了一个空间,所以arr的实际大小应该是用户传入的容量+1
        self.front = 0
        self.tail = 0
        self.size = 0

    def __str__(self):
        return str(self.arr)

    def __len__(self):
        return len(self.arr)

    def __iter__(self):
        return iter(self.arr)

    def get_size(self):
        # 获取队列元素个数
        return self.size

    def get_capaticty(self):
        # 获取队列容积(实际可存储元素个数)
        return self.__len__() - 1

    def is_full(self):
        # 判断队列是否为满
        return (self.tail+1) % len(self.arr) == self.front

    def is_empty(self):
        # 判断队列是否为空
        return self.size == 0

    def get_front(self):
        # 获取队首
        return self.arr[self.front]

    def enqueue(self, e):
        # 入队
        if self.is_full():
            self.resize(self.get_capaticty() * 2)  # 如果队列满,以当前队列容积的2倍进行扩容
        self.arr[self.tail] = e
        self.tail = (self.tail+1) % len(self.arr)
        self.size += 1

    def dequeue(self):
        # 出队
        if self.is_empty():
            raise Exception("Cannot dequeue from en empty queue")

        result = self.arr[self.front]
        self.arr[self.front] = None
        self.front = (self.front+1) % len(self.arr)
        self.size -= 1

        # 如果元素个数少于容积的1/4并且元素个数
        if self.size < self.get_capaticty() // 4 and self.get_capaticty() > 1:
            self.resize(self.get_capaticty() // 2)
        return result

    def resize(self, new_capacity):
        new_arr = [None] * (new_capacity+1)
        for i in range(self.size):
            new_arr[i] = self.arr[(i+self.front) % len(self.arr)]

        self.arr = new_arr
        self.front = 0
        self.tail = self.size

def main(loop_queue,imgs_list_path):
    start_time = datetime.datetime.now()
    for i, img_list_path in enumerate(imgs_list_path):
        loop_queue.enqueue(img_list_path)

    print('\n---------测试enqueue----------')
    print('Loop_Queue: size = {0} , capacity = {1}'.format(loop_queue.get_size(), loop_queue.get_capaticty()))
    print('loop_queue:', loop_queue)
    # print('is_empty:', loop_queue.is_empty())
    # print('is_full:', loop_queue.is_full())
    print('get_front:', loop_queue.get_front())

    print('=====队列输出结果=====')
    #算法处理完,更新数据,同时出队
    for i in range(loop_queue.get_size()):
        deq_res = loop_queue.dequeue()
        print('deq_res:', deq_res)
        #加入算法处理过程
    last_time = datetime.datetime.now() - start_time
    print('---------测试dequeue----------')
    print('Loop_Queue: size = {0} , capacity = {1}'.format(loop_queue.get_size(), loop_queue.get_capaticty()),
          loop_queue)
    # print('is_empty:', loop_queue.is_empty())
    # print('is_full:', loop_queue.is_full())
    print('get_front:', loop_queue.get_front())

    # #这个是去异步轮询查找数据库,如果没有处理的,加入队列
    # for i, img_list_path in enumerate(imgs_list_path):
    #     loop_queue.enqueue(img_list_path)
    # print(loop_queue)
if __name__ == '__main__':
    imgs_list_path = ['1.jpg', '2.jpg', '3.jpg', '4.jpg']
    loop_queue = LoopQueue()
    main(loop_queue,imgs_list_path)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 链式队列实现可以使用链表来完成,每个节点存储一个元素,以及指向下一个节点的指针。具体实现如下: 1. 定义节点结构体 ``` struct Node { int data; Node* next; }; ``` 2. 定义队列结构体 ``` struct Queue { Node* front; // 队头指针 Node* rear; // 队尾指针 }; ``` 3. 初始化队列 ``` void initQueue(Queue& q) { q.front = q.rear = new Node; q.front->next = nullptr; } ``` 4. 入队操作 ``` void enQueue(Queue& q, int x) { Node* p = new Node; p->data = x; p->next = nullptr; q.rear->next = p; q.rear = p; } ``` 5. 出队操作 ``` void deQueue(Queue& q) { if (q.front == q.rear) { cout << "队列为空,无法出队!" << endl; return; } Node* p = q.front->next; cout << "出队元素为:" << p->data << endl; q.front->next = p->next; if (q.rear == p) { q.rear = q.front; } delete p; } ``` 6. 主函数 ``` int main() { Queue q; initQueue(q); while (true) { cout << "请输入一个数字入队,或者输入一个字符出队:" << endl; char c; cin >> c; if (isdigit(c)) { int x = c - '0'; enQueue(q, x); } else { deQueue(q); } } return 0; } ``` 这样就实现了一个简单的链式队列,可以输入数字入队,输入字符出队。 ### 回答2: 链式队列是一种基于链表实现队列,它采用队尾入队、队头出队的方式来进行操作。链式队列的特点是没有大小限制,可以动态地进行扩容。对于大多数应用场景,链式队列都是一种非常高效和方便的数据结构。 根据题目要求,实现链式队列应该具有以下功能: 1. 入队:输入数字时将其插入队尾 2. 出队:输入字符时将队头元素出队 我们可以定义一个链式队列的节点类,包含数据域和指向下一个节点的指针域。同时还需要定义一个队列类,包含头尾指针。 以下是链式队列的代码实现: ```python class Node: def __init__(self, data): self.data = data self.next = None class Queue: def __init__(self): self.head = None self.tail = None def is_empty(self): return self.head is None def enqueue(self, data): new_node = Node(data) if self.tail is None: self.head = new_node self.tail = new_node else: self.tail.next = new_node self.tail = new_node def dequeue(self): if self.is_empty(): return None data = self.head.data self.head = self.head.next if self.head is None: self.tail = None return data if __name__ == '__main__': q = Queue() while True: value = input("请输入数字或字符:") if value.isdigit(): q.enqueue(int(value)) else: data = q.dequeue() if data is None: print("队列为空") else: print("队头元素为:", data) ``` 在上面的代码中,我们首先定义了一个节点类 `Node`,包含数据域和指针域,链式队列的每个节点就是一个 `Node` 的实例。然后定义了队列类 `Queue`,其中包含头指针和尾指针。 `is_empty()` 方法判断队列是否为空, `enqueue()` 方法用于入队操作, `dequeue()` 方法用于出队操作。在 `main` 函数中,我们不断地输入数字或字符,如果是数字则将其入队,如果是字符则将队头元素出队并打印出来。 总之,链式队列是一种非常高效和方便的数据结构,它可以动态地进行扩容,适用于大多数应用场景。代码实现也相对简单,只需要利用链表的基本操作实现入队和出队即可。 ### 回答3: 链式队列是一种特殊的队列,它借助链表来实现队列的功能。相对于顺序队列,它的队列长度不受限制,能够更加灵活地处理队列中的元素。 我们可以通过定义一个链式结构体来实现链式队列。对于每个队列节点,它会包含一个值(数字或字符)和一个指向下一个节点的指针。这里我们定义一个名为 `Node` 的结构体,并使用 `Option` 类型来表示队列的头节点和尾节点。代码如下: ```rust struct Node { value: Option<i32>, // 存储值 next: Option<Box<Node>>, // 指向下一个节点的指针 } struct Queue { head: Option<Box<Node>>, // 指向队列头的指针 tail: Option<Box<Node>>, // 指向队列尾的指针 } ``` 这里使用 `Option<Box<T>>` 来表示一个可选的指向类型为 `T` 的堆上分配的指针。这是为了避免处理空指针时出现 nullptr 异常。接下来我们可以定义 `Queue` 类型的方法,来实现入队和出队的操作: ```rust impl Queue { fn new() -> Self { Queue { head: None, tail: None } } fn enqueue(&mut self, val: i32) { let new_node = Box::new(Node { value: Some(val), next: None }); match self.tail.take() { Some(old_tail) => old_tail.next = Some(new_node), None => self.head = Some(new_node), } self.tail = Some(new_node); } fn dequeue(&mut self) -> Option<char> { self.head.take().map(|old_head| { let val = old_head.value.unwrap(); self.head = old_head.next; if self.head.is_none() { self.tail = None; } val as u8 as char // 将数字转换为 ASCII 字符 }) } } ``` 在 `enqueue` 方法中,我们使用 `take` 函数来获取 `tail` 字段的所有权,并将其设置为新插入节点的前一个节点。如果原本的队列为空,则将头节点指向新节点。最后,我们更新 `tail` 指向新节点。 在 `dequeue` 方法中,我们取出头节点并将其 `value` 字段进行取值。接着,我们更新 `head` 指针,并检查队列是否为空。如果队列为空,我们同时将 `tail` 指针设为 `None`。最后,我们将取出的数字转换为 ASCII 字符并返回。 为了能够让用户输入不同的元素类型(数字或字符),我们可以将 `enqueue` 方法的参数类型定义为泛型 `T`,并将节点的 `value` 字段也设为泛型类型。在 `dequeue` 方法中,我们返回的类型为 `Option<T>`。这样做的好处是可以提高代码的灵活性。最终代码如下: ```rust struct Node<T> { value: Option<T>, next: Option<Box<Node<T>>>, } struct Queue<T> { head: Option<Box<Node<T>>>, tail: Option<Box<Node<T>>>, } impl<T> Queue<T> { fn new() -> Self { Queue { head: None, tail: None } } fn enqueue(&mut self, val: T) { let new_node = Box::new(Node { value: Some(val), next: None }); match self.tail.take() { Some(old_tail) => old_tail.next = Some(new_node), None => self.head = Some(new_node), } self.tail = Some(new_node); } fn dequeue(&mut self) -> Option<T> { self.head.take().map(|old_head| { let val = old_head.value.unwrap(); self.head = old_head.next; if self.head.is_none() { self.tail = None; } val }) } } fn main() { let mut queue = Queue::new(); queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); assert_eq!(queue.dequeue(), Some(1)); assert_eq!(queue.dequeue(), Some(2)); assert_eq!(queue.dequeue(), Some(3)); queue.enqueue('a'); queue.enqueue('b'); queue.enqueue('c'); assert_eq!(queue.dequeue(), Some('a')); assert_eq!(queue.dequeue(), Some('b')); assert_eq!(queue.dequeue(), Some('c')); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值