Implementing Queues: Vector vs Linked List, Assignments of Data Structures and Algorithms

An in-depth analysis of implementing queues using vectors and linked lists. It covers the complexities of efficient vector implementations, an elegant implementation based on linked lists, and various drawings to illustrate the concepts. The document also includes code snippets for vector and linked list implementations, as well as discussions on representing linked lists as 'raw' nodes and the linked-list queue code.

Typology: Assignments

Pre 2010

Uploaded on 08/18/2009

koofers-user-m7i-1
koofers-user-m7i-1 🇺🇸

9 documents

1 / 12

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
09-1
Queues and List-Based ADT
Implementations
Problem Set: PS3 due Wednesday, March 7
Wellesley College CS230
Lecture 09
Monday, February 26
Handout #18
09-2
Overview of Today’s Lecture
1. Queues = first-in first-out (FIFO) collections.
2. Vector implementations of stacks and queues.
Efficient vector implementations of queues are
complex.
3. An elegant implementation of queues based on linked
lists.
4. Implementations of a mutable linked list abstraction.
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download Implementing Queues: Vector vs Linked List and more Assignments Data Structures and Algorithms in PDF only on Docsity!

09- 1

Queues and List-Based ADT

Implementations

Problem Set: PS3 due Wednesday, March 7

Wellesley College CS

Lecture 09

Monday, February 26

Handout

09- 2

Overview of Today’s Lecture

1. Queues = first-in first-out (FIFO) collections.

2. Vector implementations of stacks and queues.

Efficient vector implementations of queues are

complex.

3. An elegant implementation of queues based on linked

lists.

4. Implementations of a mutable linked list abstraction.

09- 3 A Queue is a FIFO Collection “bat”

A queue is like a tube. Different ends are used to

enqueue (insert) and dequeue (remove) elements.

enqueue elements here dequeue^ elements here

The enq() method enqueues an element and deq() dequeues an element.

front() returns the element at the front of the queue without removing it

back end front end “ant” “bat” “dog” “ant” “bat” “dog” “dog” “ant” Suppose q is an empty queue q.enq(“bat”) q.enq(“ant”) q.enq(“dog”) q.deq() → “bat” q.deq() → “ant” q.deq() → “dog” 09- 4 Queue Interface

import java.util.*; // imports Iterator and Iterable

/** Interface to mutable queues with elements of type T.

A queue is a first-in-first-out collection.

WARNING: the CS230 Queue interface is different than

the java.util.Queue interface. */

public interface Queue extends Iterable {

public void enq(T elt); // Add elt to back of queue.

public T deq(); // Remove and return element from front of queue.

// Throw RuntimeExecption if queue is empty.

public T front(); // Return front element of queue without removing it.

// Throw RuntimeExecption if queue is empty.

public boolean isEmpty(); // Return true if this queue is empty; else false

public int size(); // Return the number of elements in this queue

public void clear(); // Remove all elements from this queue

public Queue copy(); // Return a shallow copy of this queue

public Iterator iterator(); // Return an iterator that yields

// this queue's elements from front to back.

09- 7 A Good Array Implementation of Queues Draw pictures from class here: 09- 8 A Good Linked List Implementation of Queues “bat” “ant” “dog” back front QueueTwoEndedLinkedList q “bat” “ant” “dog” back front QueueTwoEndedLinkedList q “cat” “ant” “dog” back front QueueTwoEndedLinkedList q “cat” q.enq(“cat”) q.deq() → “bat”

09- 9 What is an Empty Queue? back front QueueTwoEndedLinkedList “dog” back front QueueTwoEndedLinkedList

We define a queue to be empty if front contains the empty list;

what back contains is irrelevant. E.g., both of the following are empty:

This simplifies the implementation of clear(), which can just

set front to the empty list.

09- 10 Equeuing into an Empty Queue back front QueueTwoEndedLinkedList “bat” back front QueueTwoEndedLinkedList

Enqueuing an element into an empty queue is a special case:

??? (can be anything)

q.enq(“bat”);

09- 13 Linked-List Queue Code: Skeleton

public class QueueTwoEndedLinkedList implements Queue {

// Instance Variables:

private ListNode front, back; // Initially contain null by default

// Constructor Methods:

public QueueTwoEndedLinkedList() {

// front is null by default, and back is irrelevant at beginning, so do nothing.

// Instance Methods

public boolean isEmpty () {

return front == null; // By design, queue is empty if front is empty

public void clear() {

front = null; // by design, don't need to modify back.

// Remaining instance methods go here

09- 14 Linked-List Queue Code: enq() public void enq (T elt) { if (isEmpty()) { // Enqueuing onto the empty list is a special case: front = new ListNode(elt, null); back = front; // initializes back for empty front } else { back.next = new ListNode(elt, null); back = back.next; } }

09- 15 Linked-List Queue Code: deq() and front()

public T deq () {

if (isEmpty()) {

throw new RuntimeException("Attempt to deq() an empty queue");

} else {

T result = front.value;

public T front () {

if (isEmpty()) {

throw new RuntimeException("Attempt to find front() of an empty queue");

} else {

return front.value;

09- 16 Linked-List Queue Code: size() and copy() public int size() { // Calculate the length of the linked list in front. int len = 0; for (ListNode current = front; current != null; current = current.next) { len++; } return len; } public Queue copy() { QueueTwoEndedLinkedList qCopy = new QueueTwoEndedLinkedList(); if (front != null) { qCopy.front = new ListNode(front.value, null); ListNode prevCopy = qCopy.front; for (ListNode current = front.next; current != null; current = current.next) { prevCopy.next = new ListNode(current.value, null); prevCopy = prevCopy.next; } } return qCopy; }

09- 19 Linked-List Queue Code: main()

public static void main (String[] args) {

// QueueTester.test performs simple tests on any queue implementation:

QueueTester.test(new QueueTwoEndedLinkedList());

q = QueueTwoEndedLinkedList[]; q.size() = 0; q.front() = Attempt to find front() of an empty queue q.enq(B); q = QueueTwoEndedLinkedList[B]; q.size() = 1; q.front() = B q.enq(C); q = QueueTwoEndedLinkedList[B,C]; q.size() = 2; q.front() = B q.enq(B); q = QueueTwoEndedLinkedList[B,C,B]; q.size() = 3; q.front() = B q.enq(A); q = QueueTwoEndedLinkedList[B,C,B,A]; q.size() = 4; q.front() = B q.deq() = B; q = QueueTwoEndedLinkedList[C,B,A]; q.size() = 3; q.front() = C q.deq() = C; q = QueueTwoEndedLinkedList[B,A]; q.size() = 2; q.front() = B q.deq() = B; q = QueueTwoEndedLinkedList[A]; q.size() = 1; q.front() = A q.enq(D); q = QueueTwoEndedLinkedList[A,D]; q.size() = 2; q.front() = A q.enq(A); q = QueueTwoEndedLinkedList[A,D,A]; q.size() = 3; q.front() = A q.enq(C); q = QueueTwoEndedLinkedList[A,D,A,C]; q.size() = 4; q.front() = A q2 = (Queue) q.copy(); q2 = QueueTwoEndedLinkedList[A,D,A,C]; q2.size() = 4; q2.front() = A q.clear(); q = QueueTwoEndedLinkedList[]; q.size() = 0; q.front() = Attempt to find front() … q2 = QueueTwoEndedLinkedList[A,D,A,C]; q2.size() = 4; q2.front() = A Iterating the elements of q2: 0:A 1:D 2:A 3:C 09- 20 An Improved Queue: Caching the Size “bat” “ant” “dog” back front QueueTwoEndedLinkedList q “bat” “ant” “dog” back front QueueTwoEndedLinkedList q “cat” q.enq(“cat”) size 3

Can change size() from a linear-time to a constant time

operation by storing it in an instance variable. For example:

size 4

09- 21 Code Modifications for Queue with Cached Sizes

public class QueueTwoEndedLinkedListBetter implements Queue {

// Instance Variables:

private ListNode front, back; // Initially contain null by default

private int size = 0;

public int size() { return size; } // Constant time, not linear time in # of elts

public void clear() { front = null; size = 0; }

public void enq (T elt) { … usual enq() code goes here … size++; }

public void deq (T elt) { … put size--; before return result … }

public Queue copy() { … put qCopy.size = size; before return qCopy … }

// All other methods are unchanged.

09- 22 MList : A Mutable Linked-List Abstraction // Static methods from CS111 lists: public static MList empty(); public static boolean isEmpty(MList L) ; public static MList prepend(T elt, MList L) ; public static T head(MList L) ; public static MList tail(MList L) // New methods for changing head and tail public static void setHead (MList L, T newHead); public static void setTail (MList L, MList newTail) // Other static methods: public static String toString (MList L); public static boolean equals (MList L1, MList L2); public static int length (MList L) public static T nth (int n, MList L); public static MList lastNode (MList L); public static MList append(MList L1, MList L2) public static MList appendD (MList L1, MList L2); public static MList postpend(MList L, T elt) public static MList postpendD (MList L, T elt); public static MList reverse (MList L) ); public static MList copy (MList L)