380 likes | 775 Views
Queue, Deque, and Priority Queue Implementations. Chapter 14. Chapter Contents. A Linked List Implementation of a Queue An Array-Based Implementation of a Queue A Circular Array A Circular Array with One Unused Location A Vector-Based Implementation of a Queue
E N D
Chapter Contents • A Linked List Implementation of a Queue • An Array-Based Implementation of a Queue • A Circular Array • A Circular Array with One Unused Location • A Vector-Based Implementation of a Queue • Circular Linked Implementations of a Queue • A Two-Part Circular Linked Chain • A Doubly Linked Implementation of a Queue • Possible Implementations of a Priority Queue
A Linked Implementation of a Queue • Use chain of linked nodes for the queue • Two ends at opposite ends of chain • Accessing last node inefficient with only head reference • Could keep a reference to the tail of the chain • With references to both • Place front of queue at beginning of chain • Place back of queue at end of chain • Remove the head is easy, remove the end requires traverse.
A Linked Implementation of a Queue Front of queue Back of queue A chain of linked nodes that implements a queue.
A Linked Implementation of a Queue • Before adding a new node to an empty chain; • (b) after adding to it. Both firstNode and lastNode points to the new node.
A Linked Implementation of a Queue • Before adding a new node to the end of a chain; • (b) after adding it.
A Linked Implementation of a Queue • A queue of more than one entry; • (b) after removing the queue's front.
A Linked Implementation of a Queue • A queue of one entry; • (b) after removing the queue's front. firstNode and lastNode both point to null
Array-Based Implementation of a Queue • Initially, let queue[0] be the front • frontIndex, backIndex are indices of front and back • If we insist queue[0] is front • Must shift entries when we remove the front • Instead, we move frontIndex • Problem then is array can become full • But now beginning of array could be empty and available for use
Array-Based Implementation of a Queue An array that represents a queue without shifting its entries: (a) initially; (b) after removing the front twice;
Array-Based Implementation of a Queue An array that represents a queue without shifting its entries: (c) after several more additions & removals; (d) after two additions that wrap around to the beginning of the array
A Circular Array • When queue reaches end of array • Add subsequent entries to beginning • Array behaves as though it were circular • First location follows last one • Use modulo arithmetic on indicesbackIndex = (backIndex + 1) % queue.length
A Circular Array A circular array that represents a queue: (a) when full; (b) after removing 2 entries; (c) after removing 3 more entries;
A Circular Array A circular array that represents a queue: (d) after removing all but one entry; (e) after removing remaining entry. Note: with circular array frontIndex == backIndex + 1 both when queue is empty and when full
A Circular Array with One Unused Location Allows us to distinguish between empty and full queue by examining frontIndex and backIndex A seven-location circular array that contains at most six entries of a queue … continued →
A Circular Array with One Unused Location (ctd.) A seven-location circular array that contains at most six entries of a queue.
A Circular Array with One Unused Location • When the array is full, the index of the unused location is 1 more than backIndex and 1 less than frontIndex. • The frontIndex == (backIndex +2) % queue.length • When the array is empty, the frontIndex == (backIndex + 1) % queue.length
Array-Based Implementation of a Queue An array-base queue: (a) initially; (b) after removing its front by incrementing frontIndex;
Array-Based Implementation of a Queue An array-base queue: (c) after removing its front by setting queue[frontIndex] to null and then incrementing frontIndex.
Vector-Based Implementation of a Queue • Maintain front of queue at beginning of vector • Use addElement(newEntry) method to add entry at back • Vector expands as necessary • When remove front element remove(0) method, remaining elements move so new front is at beginning of vector • Indexes at front and back not needed
Vector-Based Implementation of a Queue A vector that represents a queue.
Circular Linked Implementations of a Queue • Last node references first node • Now we have a single reference to last node • And still locate first node quickly by calling lastNode.getNextNode() • No node contains a null • When a class uses circular linked chain for queue • Only one data item in the class • The reference to the chain's last node
Circular Linked Implementations of a Queue A circular linked chain with an external reference to its last node that (a) has more than one node; (b) has one node; (c) is empty.
A Two-Part Linked Chain • Linked nodes that form the queue followed by linked nodes available for use in the queue • queueNode references front of queue node • freeNode references first available node following end of queue • In essence we have two chains • One for the queue • One for available nodes • All joined in a circle
A Two-Part Linked Chain Borrow the concept from circular array: addition and removals occur at ends, so it results in contiguous locations for queue elements after addition, and contiguous available locations after removals. A two-part circular linked chain that represents both a queue and the nodes available to the queue.
A Two-Part Linked Chain A two-part circular linked chain that represents a queue: (a) when it is empty; (b) after adding one entry; (c) after adding three more entries
A Two-Part Linked Chain A two-part circular linked chain that represents a queue: (d) after removing the front; (e) after adding one more entry If chain is not full, use freeNode to contain the new entry. freeNode references the next node
A Two-Part Linked Chain A chain that requires a new node for an addition to a queue: (a) before the addition; (b) after the addition. Again a queue always has at least one unused element for freeNode to point to.
A Two-Part Linked Chain A chain with a node available for an addition to a queue: (a) before the addition; (b) after the addition.
Why Two-Part Linked Chain • The available nodes are not allocated all at once the way locations are allocated for an array. • Initially no available nodes; we allocate a node each time we add a new entry. • When remove an entry, keep its node in the circle rather than deallocating it for later addition • If no available nodes, allocate a new node and link it into the chain.
Choosing Linked Implementation • You can use a linear chain • Or you can use a circular chain • Both of these implementations requires disconnection and deallocation of a node when removing a node. • If, after removing entries from the queue, you seldom add entries, these are fine. • But if you frequently add an entry after removing one, the two-part circular chain saves the time of deallocating and reallocating nodes.
A Doubly Linked Implementation of a Deque • Chain with head reference enables reference of first and then the rest of the nodes • Tail reference allows reference of last node but not next-to-last • We need nodes that can reference both • Previous node • Next node • For remove action to occur at the end of chain, thus the doubly linked chain
A Doubly Linked Implementation of a Deque A doubly linked chain with head and tail references
A Doubly Linked Implementation of a Deque Adding to the back of a non empty deque: (a) after the new node is allocated; (b) after the addition is complete.
Method Examples: addToBack Public void addToBack( T newEntry) { DLNode newNode = new DLNode(lastNode, newEntry, null); if( isEmpty()) firstNode = newNode; else lastNode.setNextNode(newNode); lastNode = newNode; }
removeBack Method Public T removeBack() { T back = null; if( !isEmpty()) { back = lastNode.getData(); lastNode = lastNode.getPreviousNode(); if( lastNode == null) firstNode = null; else lastNode.setNextNode(null); } return back; }
A Doubly Linked Implementation of a Deque (a) a deque containing at least two entries; (b) after removing first node and obtaining reference to the deque's first entry.
Possible Implementations of a Priority Queue Two possible implementations of a priority queue using (a) a sorted array; (b) a sorted chain of linked nodes. End of array and head of chain as queue head, since it is easy for remove action