Dynamic Array Deque and Queue Implementation in C, Study notes of Data Structures and Algorithms

An explanation of why a dynamic array cannot be used efficiently for a queue or deque due to the o(n) time complexity for adding or removing elements from the beginning or end. It suggests a solution to allow the starting location of the block of elements to 'float' and implement additions or removal from either front or back with constant time complexity. The document also includes the code for the deque structure and functions for adding, retrieving, and removing elements.

Typology: Study notes

Pre 2010

Uploaded on 08/30/2009

koofers-user-84a
koofers-user-84a 🇺🇸

8 documents

1 / 4

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Worksheet 20: Dynamic Array Deque and Queue Name:
An Active Learning Approach to Data Structures using C
1
Worksheet 20: Dynamic Array Deque and Queue
In Preparation: Read Chapter 7 to learn more about the Queue and Deque data types. If
you have not done it already, complete lessons 14 and 16 to learn more about the basic
features of the dynamic array data type.
A question in the worksheet on the dynamic array stack asked why you cannot use a
Dynamic Array as the basis for an efficient queue. This is because adding to or removing
from the first location (that is, index position 0) is very slow O(n).
Removing a value requires elements to slide left.
Sliding left means every element must be
moved, and hence is an O(n) operation.
Adding a value requires elements to slide right.
Sliding right opens up the location where a
new value can be inserted. Once more,
however, every element must be moved, and
hence this is an O(n) operation.
This does not mean that a Dynamic Array-like data structure cannot be used to implement
a queue. The key insight is that we can allow the starting location of the block of
elements to “float”, rather than being fixed at location zero. An internal integer data field
records the current starting location.
Notice that the “logical” index no longer corresponds to the physical index. The value
with logical index zero is found in this diagram at array location 2. The value with logical
index 1 is found at location 3, and so on.
With this change, it is now easy to implement additions or removal from either front or
back. To add to the front, simply decrement the starting location, and place the new
element in the new starting place. To add to the back, simply increase the size, and place
the new value in the location determined by the addition of the starting location and size.
But there is one subtle complexity. The block of values stored in the collection can wrap
around from the end back to the beginning:
pf3
pf4

Partial preview of the text

Download Dynamic Array Deque and Queue Implementation in C and more Study notes Data Structures and Algorithms in PDF only on Docsity!

Worksheet 20: Dynamic Array Deque and Queue

In Preparation : Read Chapter 7 to learn more about the Queue and Deque data types. If

you have not done it already, complete lessons 14 and 16 to learn more about the basic

features of the dynamic array data type.

A question in the worksheet on the dynamic array stack asked why you cannot use a

Dynamic Array as the basis for an efficient queue. This is because adding to or removing

from the first location (that is, index position 0) is very slow O(n).

Removing a value requires elements to slide left.

Sliding left means every element must be

moved, and hence is an O(n) operation.

Adding a value requires elements to slide right.

Sliding right opens up the location where a

new value can be inserted. Once more,

however, every element must be moved, and

hence this is an O(n) operation.

This does not mean that a Dynamic Array - like data structure cannot be used to implement

a queue. The key insight is that we can allow the starting location of the block of

elements to “float”, rather than being fixed at location zero. An internal integer data field

records the current starting location.

Notice that the “logical” index no longer corresponds to the physical index. The value

with logical index zero is found in this diagram at array location 2. The value with logical

index 1 is found at location 3, and so on.

With this change, it is now easy to implement additions or removal from either front or

back. To add to the front, simply decrement the starting location, and place the new

element in the new starting place. To add to the back, simply increase the size, and place

the new value in the location determined by the addition of the starting location and size.

But there is one subtle complexity. The block of values stored in the collection can wrap

around from the end back to the beginning:

Here the block of elements begins at index position 7. The next three elements are found

in index positions 8, 9 and 10. But the element after that is found at index position zero.

As with the Dynamic Array, the internal array must be reallocated and doubled if the

count of elements becomes equal to the array capacity. The internal function

_dequeDoubleCapacity will double the size of the internal buffer. The code for this

function is written for you below. You should study this to see how the variable named I

can wrap around the end of the data array as the values are copied into the new array. The

new array always begins with the starting position set to zero.

Using this idea, complete the implementation of the Deque. Implement the methods that

will add, retrieve, or remove an element from either the front or back. Explain why each

operation will have constant (or amortized constant) execution time.

void _dequeDoubleCapacity (struct deque *d) { EleType * newData; int i = d->start; int j = 0; int s; int currCap = d->capacity; if (currCap <= 0) currCap = 1; newData = malloc(2 * currCap * sizeof(EleType)); assert (newData != 0); for (s = d->size; s > 0; s--) { newData[j++] = d->data[i++]; if (i > d->capacity) i = 0; } free(d->data); d->data = newData; d->capacity = 2 * currCap; d->start = 0; } void dequeFree (struct deque *d) { free(d->data); d->size = 0; d->capacity = 0; }

void dequeRemoveFront (struct deque *d) { } void dequeRemoveBack (struct deque *d) { }