Oct 14, 2022
An ordering (A,ā¤) (an ordering over type A) is ...
An ordering needs to be...
Course 1 ⤠Course 2 iff Course 1 is a prereq of Course 2
Is this a valid ordering?
Yes!
(Partial order, as opposed to Total order)
A partial ordering needs to be...
A total ordering needs to be...
For a sort order (A,ā¤)
A partial order may not have a unique greatest/least element
⤠can be described explicitly, by a set of tuples.
{(a,a),(a,b),(a,c),ā¦,(b,b),ā¦,(z,z)}If (x,y) is in the set, xā¤y
⤠can be described by a mathematical rule.
{(x,y)|x,yāZ,āaāZ+0:x+a=y}xā¤y iff x,y are integers, and there is a non-negative integer a s.t. x+a=y
Multiple orderings can be defined for the same set.
We use a subscripts to separate orderings (e.g., ā¤1, ā¤2, ā¤3)
We can transform orderings.
Reverse: If xā¤1y, then define yā¤rx
Lexical: Given ā¤1,ā¤2,ā¤3,ā¦
⤠can be described an ordering over a key derived from the element.
xā¤edgey iff weight(x)ā¤weight(y)
xā¤studenty iff name(x)ā¤lexname(y)
We say that the weight (resp., name) is a key.
A Topological Sort of a partial order (A,ā¤1) is any total order (A,ā¤2) over A that "agrees" with (A,ā¤1)
For any two elements x,yāA:
The following are all topological sorts over our partial order example:
(If the partial order is a schedule requirement, each topological sort is a possible schedule)
And now, for an ordering-based ADT...
How do we store these items?
5, 9, 2, 7?
9, 7, 5, 2?
2, 5, 7, 9?
Base Data Structure: Linked List
def pqueueSort[A](items: Seq[A], pqueue: PriorityQueue[A]): Seq[A] =
{
val out = new Array[A](items.size)
for(item <- items){ pqueue.enqueue(item) }
i = out.size - 1
while(!pqueue.isEmpty) { buffer(i) = pqueue.dequeue; i-- }
return out.toSeq
}
Seq/Buffer | PQueue | |
---|---|---|
Input | (7, 4, 8, 2, 5, 3, 9) | () |
Step 1 | (4, 8, 2, 5, 3, 9) | (7) |
Step 2 | (8, 2, 5, 3, 9) | (7, 4) |
į§ į§ į§ | ||
Step N | [_, _, _, _, _, _, _] | (7, 4, 8, 2, 5, 3, 9) |
Step N+1 | [_, _, _, _, _, _, 9] | (7, 4, 8, 2, 5, 3) |
Step N+2 | [_, _, _, _, _, 8, 9] | (7, 4, 2, 5, 3) |
Step N+3 | [_, _, _, _, 7, 8, 9] | (4, 2, 5, 3) |
Step N+4 | [_, _, _, 5, 7, 8, 9] | (4, 2, 3) |
Step N+5 | [_, _, 4, 5, 7, 8, 9] | (2, 3) |
Step N+6 | [_, 3, 4, 5, 7, 8, 9] | (2) |
Step 2N | [2, 3, 4, 5, 7, 8, 9] | () |
def pqueueSort[A](items: Seq[A], pqueue: PriorityQueue[A]): Seq[A] =
{
val out = new Array[A](items.size)
for(item <- items){ pqueue.enqueue(item) }
i = out.size - 1
while(!pqueue.isEmpty) { buffer(i) = pqueue.dequeue; i-- }
return out.toSeq
}
What's the complexity?
Base Data Structure: Linked List
Seq/Buffer | PQueue | |
---|---|---|
Input | (7, 4, 8, 2, 5, 3, 9) | () |
Step 1 | (4, 8, 2, 5, 3, 9) | (7) |
Step 2 | (8, 2, 5, 3, 9) | (7, 4) |
Step 3 | (2, 5, 3, 9) | (8, 7, 4) |
Step 4 | (5, 3, 9) | (8, 7, 4, 2) |
Step 5 | (3, 9) | (8, 7, 5, 4, 2) |
Step 6 | (9) | (8, 7, 5, 4, 3, 2) |
Step N | [_, _, _, _, _, _, _] | (9, 8, 7, 5, 4, 3, 2) |
Step N+1 | [_, _, _, _, _, _, 9] | (8, 7, 5, 4, 3, 2) |
į§ į§ į§ | ||
Step 2N | [2, 3, 4, 5, 7, 8, 9] | () |
def pqueueSort[A](items: Seq[A], pqueue: PriorityQueue[A]): Seq[A] =
{
val out = new Array[A](items.size)
for(item <- items){ pqueue.enqueue(item) }
i = out.size - 1
while(!pqueue.isEmpty) { buffer(i) = pqueue.dequeue; i-- }
return out.toSeq
}
What's the complexity?
Operation | Lazy | Proactive |
---|---|---|
enqueue | O(1) | O(n) |
dequeue | O(n) | O(1) |
head | O(n) | O(1) |
Can we do better?