Skip to content

Commit 2e27f22

Browse files
committed
Clean up of Bounded Priority Queue
1 parent dda4729 commit 2e27f22

File tree

3 files changed

+207
-159
lines changed

3 files changed

+207
-159
lines changed

Bounded Priority Queue/BoundedPriorityQueue.swift

Lines changed: 76 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,98 +4,95 @@
44
// Created by John Gill on 2/28/16.
55
//
66

7-
import Foundation
8-
97
public class LinkedListNode<T: Comparable> {
10-
var value: T
11-
var next: LinkedListNode?
12-
var previous: LinkedListNode?
13-
14-
public init(value: T) {
15-
self.value = value
16-
self.next = nil
17-
self.previous = nil
18-
}
8+
var value: T
9+
var next: LinkedListNode?
10+
var previous: LinkedListNode?
11+
12+
public init(value: T) {
13+
self.value = value
14+
self.next = nil
15+
self.previous = nil
16+
}
1917
}
2018

2119
public class BoundedPriorityQueue<T: Comparable> {
22-
public typealias Node = LinkedListNode<T>
23-
private var head: Node?
24-
private var curNumElements:Int
25-
private var maxNumElements: Int
26-
27-
public init(maxElements:Int) {
28-
head = nil
29-
maxNumElements = maxElements
30-
curNumElements = 0
31-
}
32-
33-
public var isEmpty: Bool {
34-
return curNumElements == 0
35-
}
36-
37-
public var count: Int {
38-
return curNumElements
39-
}
20+
private typealias Node = LinkedListNode<T>
4021

41-
public func peek() -> T? {
42-
if curNumElements > 0 {
43-
return head!.value
44-
}
45-
return nil
46-
}
22+
private(set) public var count = 0
23+
private var head: Node?
24+
private var maxElements: Int
4725

48-
public func enqueue(value: T) {
49-
let newNode = Node(value: value)
26+
public init(maxElements: Int) {
27+
self.maxElements = maxElements
28+
}
5029

51-
if head == nil {
52-
head = newNode
53-
} else {
54-
var node = head
55-
if curNumElements == maxNumElements && newNode.value > node!.value {
56-
return
57-
}
30+
public var isEmpty: Bool {
31+
return count == 0
32+
}
5833

59-
while (node!.next != nil) && (newNode.value < node!.value) { node = node!.next }
34+
public func peek() -> T? {
35+
return head?.value
36+
}
6037

61-
if newNode.value < node!.value {
62-
newNode.next = node!.next
63-
newNode.previous = node
38+
public func enqueue(value: T) {
39+
let newNode = Node(value: value)
6440

65-
if(newNode.next != nil) { /* TAIL */
66-
newNode.next!.previous = newNode
67-
}
68-
node!.next = newNode
69-
} else {
70-
newNode.previous = node!.previous
71-
newNode.next = node
72-
if(node!.previous == nil) { /* HEAD */
73-
head = newNode
74-
} else {
75-
node!.previous!.next = newNode
76-
}
77-
node!.previous = newNode
78-
}
79-
if(curNumElements == maxNumElements) { dequeue() }
80-
}
81-
curNumElements += 1
41+
if head == nil {
42+
head = newNode
43+
count = 1
44+
return
8245
}
8346

84-
public func dequeue() -> T? {
85-
if curNumElements > 0 {
86-
let retVal = head!.value
47+
var node = head
48+
if count == maxElements && newNode.value > node!.value {
49+
return
50+
}
51+
52+
while (node!.next != nil) && (newNode.value < node!.value) {
53+
node = node!.next
54+
}
55+
56+
if newNode.value < node!.value {
57+
newNode.next = node!.next
58+
newNode.previous = node
59+
60+
if newNode.next != nil { /* TAIL */
61+
newNode.next!.previous = newNode
62+
}
63+
node!.next = newNode
64+
} else {
65+
newNode.previous = node!.previous
66+
newNode.next = node
67+
if node!.previous == nil { /* HEAD */
68+
head = newNode
69+
} else {
70+
node!.previous!.next = newNode
71+
}
72+
node!.previous = newNode
73+
}
8774

88-
if curNumElements == 1 {
89-
head = nil
90-
}
91-
else {
92-
head = head!.next
93-
head!.previous = nil
94-
}
75+
if count == maxElements {
76+
dequeue()
77+
}
78+
count += 1
79+
}
80+
81+
public func dequeue() -> T? {
82+
if count == 0 {
83+
return nil
84+
}
9585

96-
curNumElements -= 1
97-
return retVal
98-
}
99-
return nil
86+
let retVal = head!.value
87+
88+
if count == 1 {
89+
head = nil
90+
} else {
91+
head = head!.next
92+
head!.previous = nil
10093
}
94+
95+
count -= 1
96+
return retVal
97+
}
10198
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Bounded Priority queue
2+
3+
A bounded priority queue is similar to a regular [priority queue](../Priority Queue/), except that there is a fixed upper bound on the number of elements that can be stored. When a new element is added to the queue while the queue is at capacity, the element with the highest priority value is ejected from the queue.
4+
5+
## Example
6+
7+
Suppose we have a bounded-priority-queue with maximum size 5 that has the following values and priorities:
8+
9+
```
10+
Value: [ A, B, C, D, E ]
11+
Priority: [ 0.1, 0.25, 1.33, 3.2, 4.6 ]
12+
```
13+
14+
Here, we consider the object with the lowest priority value to be the most important (so this is a *min-priority* queue). The larger the priority value, the less we care about the object. So `A` is more important than `B`, `B` is more important than `C`, and so on.
15+
16+
Now we want to insert the element `F` with priority `0.4` into this bounded priority queue. Because the queue has maximum size 5, this will insert the element `F` but then evict the lowest-priority element (`E`), yielding the updated queue:
17+
18+
```
19+
Value: [ A, B, F, C, D ]
20+
Priority: [ 0.1, 0.25, 0.4, 1.33, 3.2 ]
21+
```
22+
23+
`F` is inserted between `B` and `C` because of its priority value. It's less important than `B` but more important than `C`.
24+
25+
Suppose that we wish to insert the element `G` with priority 4.0 into this BPQ. Because `G`'s priority value is greater than the maximum-priority element in the queue, upon inserting `G` it will immediately be evicted. In other words, inserting an element into a BPQ with priority greater than the maximum-priority element of the BPQ has no effect.
26+
27+
## Implementation
28+
29+
While a [heap](../Heap/) may be a really simple implementation for a priority queue, a sorted [linked list](../Linked List/) allows for **O(k)** insertion and **O(1)** deletion, where **k** is the bounding number of elements.
30+
31+
Here's how you could implement it in Swift:
32+
33+
```swift
34+
public class BoundedPriorityQueue<T: Comparable> {
35+
private typealias Node = LinkedListNode<T>
36+
37+
private(set) public var count = 0
38+
private var head: Node?
39+
private var maxElements: Int
40+
41+
public init(maxElements: Int) {
42+
self.maxElements = maxElements
43+
}
44+
45+
public var isEmpty: Bool {
46+
return count == 0
47+
}
48+
49+
public func peek() -> T? {
50+
return head?.value
51+
}
52+
```
53+
54+
The `BoundedPriorityQueue` class contains a doubly linked list of `LinkedListNode` objects. Nothing special here yet. The fun stuff happens in the `enqueue()` method:
55+
56+
```swift
57+
public func enqueue(value: T) {
58+
let newNode = Node(value: value)
59+
60+
if head == nil {
61+
head = newNode
62+
count = 1
63+
return
64+
}
65+
66+
var node = head
67+
if count == maxElements && newNode.value > node!.value {
68+
return
69+
}
70+
71+
while (node!.next != nil) && (newNode.value < node!.value) {
72+
node = node!.next
73+
}
74+
75+
if newNode.value < node!.value {
76+
newNode.next = node!.next
77+
newNode.previous = node
78+
79+
if newNode.next != nil { /* TAIL */
80+
newNode.next!.previous = newNode
81+
}
82+
node!.next = newNode
83+
} else {
84+
newNode.previous = node!.previous
85+
newNode.next = node
86+
if node!.previous == nil { /* HEAD */
87+
head = newNode
88+
} else {
89+
node!.previous!.next = newNode
90+
}
91+
node!.previous = newNode
92+
}
93+
94+
if count == maxElements {
95+
dequeue()
96+
}
97+
count += 1
98+
}
99+
```
100+
101+
We first check if the queue already has the maximum number of elements. If so, and the new priority value is greater than the `head` element's priority value, then there is no room for this new element and we return without inserting it.
102+
103+
If the new value is acceptable, then we search through the list to find the proper insertion ___location and update the `next` and `previous` pointers.
104+
105+
Lastly, if the queue has now reached the maximum number of elements, then we `dequeue()` the one with the largest priority value.
106+
107+
By keeping the most important element at the front of the list, it makes dequeueing very easy:
108+
109+
```swift
110+
public func dequeue() -> T? {
111+
if count == 0 {
112+
return nil
113+
}
114+
115+
let retVal = head!.value
116+
117+
if count == 1 {
118+
head = nil
119+
} else {
120+
head = head!.next
121+
head!.previous = nil
122+
}
123+
124+
count -= 1
125+
return retVal
126+
}
127+
```
128+
129+
This simply removes the `head` element from the list and returns it.
130+
131+
*Written for Swift Algorithm Club by John Gill and Matthijs Hollemans*

Bounded Priority Queue/README.md

Lines changed: 0 additions & 80 deletions
This file was deleted.

0 commit comments

Comments
 (0)