Theoretical basis of stacks and queues

Theoretical basis of stacks and queues

1. The difference between stack and queue

(1) Lists in python are implemented in the form of linked lists. Therefore, when creating a Python list, there is no need to specify a data structure or the length of the list. Correspondingly, the array must be declared when it is created
. data type, the length of the array must also be specified

(2) Memory address:
List: Discontinuous
Array: Continuous

(3) Data type
List: The elements inside can be of any data type
Array: The same type

Since the data types in an array are all the same, all items in the array have the same data type, so operations behave the same way on each element. Therefore, arrays are very useful when dealing with large numbers of homogeneous data types . Because Python does not have to remember the data type details of each element individually, arrays may be faster and use less memory than lists

  • Stack and queue are two basic data structures, both of which are container types. The difference between the two is as follows:
    stack: last in first out
    Insert image description here

queue: first in first out
Insert image description here

Note: stack and queue cannot be operated by querying the element at a specific position. But their arrangement is in order .

2. Implementation of stack in python

For stack, we can use python's built-in list implementation, because list is a linear array, and the time taken to insert and delete an element at the end is O(1), which is very consistent with the requirements of stack. Of course, you can also use lists. The implementation code of stack (using Python's built-in list) is simple to implement. The code is as follows:

class Stack(object):
    def __init__(self):
        self.stack = []
    
    def push(self,value):  #进栈
        self.stack.append(value)
    
    def pop(self):   #出栈
        if self.stack:
            self.stack.pop()
        else:
            raise LookupError('stack is empty') #无效数据查询
    
    def is_empty(self): ##判断栈是否为空
        return bool(self.stack)
    
    def top(self): #取出栈中最新的元素
        return self.stack[-1]

3. Implementation of queue

We define the following linked list to implement the queue data structure
Insert image description here

Define a head node, with the left pointing to the beginning of the queue and the right pointing to the end of the queue. This ensures that inserting an element and taking out an element are both O(1) operations. It is also very convenient to use this kind of linked list to implement queue. Code The implementation is as follows:

class Head(object):
    def __init__(self):
        self.left = None
        self.right = None

    def Node(object):
        def __init__(self,value):
            self.value = value
            self.next = None

class queue(object):
    def __init__(self):
        #初始化节点
        self.head = Head()
    
    def enqueue(self,value):
        #插入一个元素
        newnode = Node(value)
        p = self.head
        if p.right:
            #如果head节点的右边不为None,
            #说明队列中有其他元素
            temp = p.right
            temp.next = newnode
            p.right = newnode
        else:
            #此时说明队列为空
            p.right = newnode
            p.left = newnode
    
    def dequeue(self):
        #取出一个元素
        p = self.head
        if p.left and (p.left == p.right):
            #说明队中只有一个元素
            temp = p.left
            p.left = p.right = None
            return temp.value
        elif p.left and (p.left != p.right):
            #说明队中不只一个元素
            temp = p.left
            p.left = temp.next
            return temp.value
        else:
            #说明队列为空
            raise LookupError('queue is empty!')
    
    def is_empty(self):
        if self.head.left:
            return False
        else:
            return True
    
    def top(self):
        #查询队列中最先入队的元素
        if self.head.left:
            return self.head.left.value
        else:
            raise LookupError('queue is empty!')

4.Python’s built-in heap, stack and queue

summary

Insert image description here

Specific use

heapq heap queue

heapq is a built-in heap structure, a special form of complete binary tree, in which the value of the parent node is always greater than the child node. According to its properties, python can use one that satisfies heap[k] <= heap[2 * k + 1] < = heap[2 * k + 2] to achieve the list. Heapq is the minimum heap. If you want to achieve the maximum heap, you can use some tricks. For example, when heappush, fill in the data * -1, and then when heappop, multiply the popped elements by -1.

import heapq

heap = []
heapq.heappush(heap, 3)
heapq.heappush(heap, 2)
heapq.heappush(heap, 1)
print(heap)  # 输出为 [1, 3, 2]

# 要想有序输出 堆的元素
heapq.heappop(heap) # 输出1
heapq.heappop(heap) # 输出2
heapq.heappop(heap) # 输出3

# 要想输出前n个最大值,前n个最小值,可以使用
heapq.nlargest(n, heap)
heapq.nsmallest(n, heap)
deque double-ended queue

from collections import deque can implement stack or queue functions, because double-ended queues can be edited at the head and tail of the queue, so if we want to implement stack functions in python, the best choice is deque. Of course we can also use ordinary array structures.

Ordinary queue operations are to insert elements at the end of the queue and then pop elements out of the head:

dq = queue()
dq.append(3)  # deque([3])
dq.append(4)  # deque([3, 4])
dq.popleft() # 弹出 3,并且dq为 deque([4])
如果设置为一个栈的话,FILO,那么就是如下的代码

dq = queue()
dq.append(3)  # deque([3])
dq.append(4)  # deque([3, 4])
dq.pop() # 弹出 4,并且dq为 deque([3])
queue

Queue queue is a thread-safe package. There are many structures in this package, such as stack LifoQueue. If you want to use it in a concurrent environment, it is best to use this structure, because if the stack is empty, the top element of the stack will be popped. If so, blocking will occur until the stack is not empty.

LifoQueue

LifoQueue is a stack structure with push and exit operations. The methods are put() and get() respectively, and get() will block when LifoQueue() is empty.

from queue import LifoQueue

s = LifoQueue()
s.put(3)
s.put(4)
print(s.get()) # 打印4
print(s.get()) # 打印3
print(s.get()) # 一直等待直到s中存在元素,然后就打印退出
Queue

Queue is a queue with enqueue and dequeue operations. The methods are put() and get() respectively, and get() will block when the Queue is empty. In addition, the length of the queue can also be set. If the length of the queue is not set, , or set the length of the queue to a number less than or equal to 0, then the length of the queue is infinite. You can obtain the maximum length of the queue through the .maxsize attribute.

from queue import Queue

q = Queue()
q.put(3)
q.put(4)
print(q.get()) # 打印3
print(q.get()) # 打印4
print(q.get()) # 一直等待直到q中存在元素,然后就打印退出
print(q.get_nowait()) # 如果队列q为空,那么不会等待,而是输出 Empty 的异常
PriorityQueue

PriorityQueue is a priority queue. The elements of the queue are sorted, so you can use the priority queue for a sorted sequence, which can efficiently obtain the largest or smallest element.
In the scenario of scheduling problems, the priority queue is often used. It mainly includes the operation of obtaining the maximum or minimum value and the enqueuing operation. The
priority queue encapsulates heapq internally. The difference is that the priority queue is thread-safe and can be used concurrently. Environment should choose to use PriorityQueue

from queue import PriorityQueue

pq = PriorityQueue()
pq.put((2, 'name'))
pq.put((1, 'age'))
pq.put((3, 'job'))
while not pq.empty():
    print(pq.get())

"""
输出内容如下
(1, "age")
(2, "name")
(3, "job")
"""
multiprocessing.Queue

The multi-process version of the queue multiprocessing.Quque. If you want to use the queue in a multi-process environment, you should choose multiprocessing.Queue
. Its enqueue and dequeue operations are put() and get() respectively.


参考文章:
[1]https://blog.csdn.net/weixin_43026262/article/details/104291381
[2]https://www.jianshu.com/p/9b94651534c3
[3]https://zhuanlan.zhihu.com/p/110424854

Guess you like

Origin blog.csdn.net/qq_42859625/article/details/129487213