|
| 1 | +# Queues in Python |
| 2 | + |
| 3 | +A queue is a linear data structure where elements are added at the back (enqueue) and removed from the front (dequeue). Imagine a line at a coffee shop, the first in line (front) gets served first, and new customers join at the back. This FIFO approach ensures order and fairness in processing elements. |
| 4 | + |
| 5 | +Queues offer efficient implementations for various scenarios. They are often used in: |
| 6 | +- **Task Scheduling** - Operating systems utilize queues to manage processes waiting for CPU time. |
| 7 | +- **Breadth-first search algorithms** - Traversing a tree or graph involves exploring neighbouring nodes level by level, often achieved using a queue. |
| 8 | +- **Message passing** - Communication protocols leverage queues to buffer messages between applications for reliable delivery. |
| 9 | + |
| 10 | +## Types of Queue |
| 11 | + |
| 12 | +A queue can be classified into 4 types - |
| 13 | + |
| 14 | +- **Simple Queue** - A simple queue is a queue, where we can only insert an element at the back and remove the element from the front of the queue, this type of queue follows the FIFO principle. |
| 15 | +- **Double-Ended Queue (Dequeue)** - In this type of queue, insertions and deletions of elements can be performed from both ends of the queue.<br> |
| 16 | +Double-ended queues can be classified into 2 types -> |
| 17 | + - **Input-Restricted Queue** |
| 18 | + - **Output-Restricted Queue** |
| 19 | +- **Circular Queue** - It is a special type of queue where the back is connected to the front, where the operations follow the FIFO principle. |
| 20 | +- **Priority Queue** - In this type of queue, elements are accessed based on their priority in the queue. <br> |
| 21 | +Priority queues are of 2 types -> |
| 22 | + - **Ascending Priority Queue** |
| 23 | + - **Descending Priority Queue** |
| 24 | + |
| 25 | +## Real Life Examples of Queues |
| 26 | +- **Customer Service** - Consider how a customer service phone line works. Customers calling are put into a queue. The first customer to call is the first one to be served (FIFO). As more customers call, they are added to the end of the queue, and as customers are served, they are removed from the front. The entire process follows the queue data structure. |
| 27 | + |
| 28 | +- **Printers** - Printers operate using a queue to manage print jobs. When a user sends a document to the printer, the job is added to the queue (enqueue). Once a job completes printing, it's removed from the queue (dequeue), and the next job in line starts. This sequential order of handling tasks perfectly exhibits the queue data structure. |
| 29 | + |
| 30 | +- **Computer Memory** - Certain types of computer memory use a queue data structure to hold and process instructions. For example, in a computer's cache memory, the fetch-decode-execute cycle of an instruction follows a queue. The first instruction fetched is the first one to be decoded and executed, while new instructions fetched are added to the rear. |
| 31 | + |
| 32 | +<hr> |
| 33 | + |
| 34 | +# Important Terminologies in Queues |
| 35 | + |
| 36 | +Understanding these terms is crucial for working with queues: |
| 37 | + |
| 38 | +- **Enqueue** - Adding an element to the back of the queue. |
| 39 | +- **Dequeue** - Removing the element at the front of the queue. |
| 40 | +- **Front** - The first element in the queue, to be removed next. |
| 41 | +- **Rear/Back** - The last element in the queue, where new elements are added. |
| 42 | +- **Empty Queue** - A queue with no elements. |
| 43 | +- **Overflow** - Attempting to enqueue an element when the queue is full. |
| 44 | +- **Underflow** - Attempting to dequeue an element from an empty queue. |
| 45 | + |
| 46 | +## Operations on a Queue |
| 47 | + |
| 48 | +There are some key operations in a queue that include - |
| 49 | + |
| 50 | +- **isFULL** - This operation checks if a queue is full. |
| 51 | +- **isEMPTY** - This operation checks if a queue is empty. |
| 52 | +- **Display** - This operation displays the queue elements. |
| 53 | +- **Peek** - This operation is the process of getting the front value of a queue, without removing it. (i.e., Value at the front). |
| 54 | + |
| 55 | +<hr> |
| 56 | + |
| 57 | +# Implementation of Queue |
| 58 | + |
| 59 | +```python |
| 60 | +def isEmpty(Qu): |
| 61 | + if Qu == []: |
| 62 | + return True |
| 63 | + else: |
| 64 | + return False |
| 65 | + |
| 66 | +def Enqueue(Qu, item) : |
| 67 | + Qu.append(item) |
| 68 | + if len(Qu) == 1: |
| 69 | + front = rear = 0 |
| 70 | + else: |
| 71 | + rear = len(Qu) - 1 |
| 72 | + print(item, "enqueued to queue") |
| 73 | +def Dequeue(Qu): |
| 74 | + if isEmpty(Qu): |
| 75 | + print("Underflow") |
| 76 | + else: |
| 77 | + item = Qu.pop(0) |
| 78 | + if len(Qu) == 0: #if it was single-element queue |
| 79 | + front = rear = None |
| 80 | + print(item, "dequeued from queue") |
| 81 | + |
| 82 | +def Peek(Qu): |
| 83 | + if isEmpty(Qu): |
| 84 | + print("Underflow") |
| 85 | + else: |
| 86 | + front = 0 |
| 87 | + print("Frontmost item is :", Qu[front]) |
| 88 | + |
| 89 | +def Display(Qu): |
| 90 | + if isEmpty(Qu): |
| 91 | + print("Queue Empty!") |
| 92 | + elif len(Qu) == 1: |
| 93 | + print(Qu[0], "<== front, rear") |
| 94 | + else: |
| 95 | + front = 0 |
| 96 | + rear = len(Qu) - 1 |
| 97 | + print(Qu[front], "<-front") |
| 98 | + for a in range(1, rear): |
| 99 | + print(Qu[a]) |
| 100 | + print(Qu[rear], "<-rear") |
| 101 | + |
| 102 | +queue = [] #initially queue is empty |
| 103 | +front = None |
| 104 | + |
| 105 | +# Example Usage |
| 106 | +Enqueue(queue, 1) |
| 107 | +Enqueue(queue, 2) |
| 108 | +Enqueue(queue, 3) |
| 109 | +Dequeue(queue) |
| 110 | +Peek(queue) |
| 111 | +Display(queue) |
| 112 | +``` |
| 113 | + |
| 114 | +## Output |
| 115 | + |
| 116 | +``` |
| 117 | +1 enqueued to queue |
| 118 | +2 enqueued to queue |
| 119 | +3 enqueued to queue |
| 120 | +1 dequeued from queue |
| 121 | +Frontmost item is : 2 |
| 122 | +2 <-front |
| 123 | +3 <-rear |
| 124 | +``` |
| 125 | + |
| 126 | +## Complexity Analysis |
| 127 | + |
| 128 | +- **Worst case**: `O(n^2)` This occurs when the code performs lots of display operations. |
| 129 | +- **Best case**: `O(n)` If the code mostly performs enqueue, dequeue and peek operations. |
| 130 | +- **Average case**: `O(n^2)` It occurs when the number of operations in display are more than the operations in enqueue, dequeue and peek. |
0 commit comments