0% found this document useful (0 votes)
24 views56 pages

Vectors Lists Sequences Skip Lists

Uploaded by

dia.batra0704
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views56 pages

Vectors Lists Sequences Skip Lists

Uploaded by

dia.batra0704
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 56

Vectors, Lists, and Sequences

The Vector ADT


• The Vector ADT extends the notion of array by storing a
sequence of arbitrary objects
• An element can be accessed, inserted or removed by
specifying its index/rank (number of elements preceding it)
• An exception is thrown if an incorrect rank is specified (e.g.,
a negative rank)
The Vector ADT
A vector, also called an array list, is an ADT that supports
the following fundamental functions
In all cases, the index parameter i is assumed to be in the
range 0 ≤ i ≤ size()−1.
– at(i): Return the element of V with index i; an error
condition occurs if i is out of range.
– set(i,e): Replace the element at index i with e; an error
condition occurs if i is out of range.
– insert(i,e): Insert a new element e into V to have index i;
an error condition occurs if i is out of range.
– erase(i): Remove fromV the element at index i; an error
condition occurs if i is out of range.
– Additional operations size() and isEmpty()
The Vector ADT
Applications of Vectors
• Direct applications
– Sorted collection of objects (simple database)
• Indirect applications
– Auxiliary data structure for algorithms
– Component of other data structures
Array-based Vector
• Use an array V of size N
• A variable n keeps track of the size of the vector
(number of elements stored)
• Operation at(r) is implemented in O(1) time by
returning V[r]

0 N-1
V
0 1 2 r n
Array based Vector: Insertion
• In operation insert(r,e) we need to make
room for the new element by shifting forward
the n  r elements V[r], …, V[n  1]
• In the worst case (r  0), this takes O(n) time

V
0 1 2 r n

V
0 1 2 r n

V o
0 1 2 r n
Deletion
• In operation erase(r) we need to fill the hole left
by the removed element by shifting backward the n
 r  1 elements V[r  1], …, V[n  1]
• In the worst case (r  0), this takes O(n) time

V o
0 1 2 r n

V
0 1 2 r n

V
0 1 2 r n
Insertion and Deletion Code
Performance
• In the array based implementation of a Vector
– The space used by the data structure is O(n)
– size(), empty(), at(r) and set(i,e) run in O(1) time
– insert(i,e) and erase(i) run in O(n) time
• If we use the array in a circular fashion, insert(i,e)
and erase(i) run in O(1) time
• In an insert(i,e) operation, when the array is full,
instead of throwing an exception, we can replace
the array with a larger one
Performance
Exercise:
• Implement the Deque ADT using Vector functions
– Deque functions:
• first(), last(), insertFirst(e), insertLast(e), removeFirst(),
removeLast(), size(), isEmpty()
– Vector functions:
• at(i), set(i,e), insert(i,e), erase(i), size(), empty()
Exercise Solution:
• Implement the Deque ADT using Vector functions
– Deque functions: first(), last(), insertFirst(e), insertLast(e), removeFirst(), removeLast(), size(), isEmpty()
– Vector functions: elemAtRank( r), replaceAtRank(r,e), insertAtRank(r,e), removeAtRank(r ), size(), isEmpty()

– Deque function : Realization using Vector Functions


– size() and isEmpty() fcns can simply call Vector fcns
directly
– first() => at(0)
– last() => at(size()-1)
– insertFirst(e) => insert(0,e)
– insertLast(e) => insert(size(), e)
– removeFirst() => erase(0)
– removeLast() => erase(size()-1)
An Extendable Array
Implementation

when an overflow occurs, that is, when n=N and


function insert is called, we perform the following
steps:
1. Allocate a new array B of capacity N
2. Copy A[i] to B[i], for i = 0, . . . ,N −1
3. Deallocate A and reassign A to point to the new
array B
An Extendable Array
Implementation
An Extendable Array
Implementation
An Extendable Array
Implementation
An Extendable Array Efficiency
• Array replacement strategy might, at first, seem rather
slow.
• One array replacement required by an element insertion
takes O(n) time, which is not very good.
• However, new array allows us to add n new elements to
the vector before the array must be replaced again.
• As a shorthand notation, let us refer to the insertion of an
element meant to be the last element in a vector as a “push”
operation.
• Using amortization, we can show that performing a sequence of
push operations on a vector implemented with an extendable
array is quite efficient
An Extendable Array Efficiency
Proposition 6.2: Let V be a vector implemented by means of
an extendable array A, as described above. The total time to
perform a series of n push operations in V, starting from V
being empty and A having size N = 1, is O(n).
• Let us assume that one cyber-dollar is enough to pay for
the execution of each push operation in V, excluding the
time spent for growing the array.
• Also, let us assume that growing the array from size k to
size 2k requires k cyber-dollars for the time spent copying
the elements.
• Total charge for each push operation will be three cyber
dollars.
• Thus, we overcharge each push operation that does not
cause an overflow by two cyber-dollars. Think of the two
cyber-dollars profited in an insertion that does not grow the
array as being “stored” at the element inserted.
An Extendable Array Efficiency
• An overflow occurs when the vector V has 2i
elements, for some i ≥ 0, and the size of the
array used by V is 2i.
• Thus, doubling the size of the array requires 2i
cyber-dollars.
• These cyber-dollars can be found at the elements
stored in cells 2i−1 through 2i.
• Therefore, we have a valid amortization scheme
in which each operation is charged three cyber-
dollars and all the computing time is paid for.
That is, we can pay for the execution of n push
operations using 3n cyber-dollars.
An Extendable Array Efficiency
STL vector class
• STL is abbreviation for C++ Standard Template Library.
• STL provides C++ programmers a number of useful built-in
classes and algorithms. A container is a data structure that
stores a collection of objects.
• The class vector is perhaps the most basic example of an STL
container class.
STL vector class
• STL vectors behave much like standard arrays in C++, but
they are superior to standard arrays in many respects.
– As with arrays, individual elements of a vector object can be
indexed using the usual index operator (“[ ]”). Elements can also
be accessed by a member function called at. The advantage of
this member function over the index operator is that it performs
range checking and generates an error exception if the index is
out of bounds.
– Unlike C++ arrays, STL vectors can be dynamically resized, and
new elements may be efficiently appended or removed from the
end of an array.
– When an STL vector of class objects is destroyed, it automatically
invokes the destructor for each of its elements. (With C++ arrays,
it is the obligation of the programmer to do this explicitly.)
– STL vectors provide a number of useful functions that operate on
entire vectors, not just on individual elements. This includes, for
example, the ability to copy all or part of one vector to another,
the ability to compare the contents of two arrays, and the ability
to insert and erase multiple elements.
STL vector class
The principal member functions of the vector class :
Let V be declared to be an STL vector of some base type, and let e denote a single
object of this same base type. (For example, V is a vector of integers, and e is an
integer.)
•vector(n): Construct a vector with space for n elements; if no argument is
given, create an empty vector.
•size(): Return the number of elements in V.
•empty(): Return true if V is empty and false otherwise.
•resize(n): Resize V, so that it has space for n elements.
•reserve(n): Request that the allocated storage space be large enough to hold
n elements.
•operator[i]: Return a reference to the ith element of V.
•at(i): Same as V[i], but throw an out of range exception if i is out of bounds,
that is, if i < 0 or i ≥V.size().
•front(): Return a reference to the first element of V.
•back(): Return a reference to the last element of V.
•push back(e): Append a copy of the element e to the end of V, thus
increasing its size by one.
•pop back(): Remove the last element of V, thus reducing its size by one.
STL vector class
• When the base type of an STL vector is class, all copying of elements
(for example, in push back) is performed by invoking the class’s copy
constructor.
• Also, when elements are destroyed (for example, by invoking the
destroyer or the pop back member function) the class’s destructor is
invoked on each deleted element.
• STL vectors are expandable—when the current array space is
exhausted, its storage size is increased.
• STL vector also supports functions for inserting elements at arbitrary
positions within the vector, and for removing arbitrary elements of
the vector.
STL vector class
Similarities & Differences with book’s Vector ADT
•One difference is that the STL constructor allows for an arbitrary
number of initial elements, whereas our ArrayVect constructor
always starts with an empty vector.
•The STL vector functions V.front() and V.back() are equivalent to
our functions V[0] and V[n−1], respectively, where n is equal to
V.size().
•The STL vector functions V.push back(e) and V.pop back() are
equivalent to our ArrayVect functions V.insert(n,e) and
V.remove(n−1), respectively
Vector Summary
• Vector Operation Complexity for Different
Implementations
Array List
Fixed-Size or Singly or
Expandable Doubly
Linked

RemoveAtRank(r), O(1) Best Case (r=0,n) ?


InsertAtRank(r,o) O(n) Worst Case
O(n) Average Case
elemAtRank(r), O(1) ?
ReplaceAtRank(r,o)
Size(), isEmpty() O(1) ?
Lists and Sequences
List ADT
• List ADT abstracts the concrete linked list data structure using a
related position ADT that abstracts the notion of “place” in a list.
• The List ADT models a sequence of positions storing arbitrary
objects
– establishes a before/after relation between positions
• It allows for insertion and removal in the “middle”
• It allows for node-based operations like a hypothetical function
remove(v) that removes the element of L stored at node v of the
list.
• Such functions could provide significant speedups over index-based
functions
Position ADT
• The Position ADT models the notion of place within a data
structure where a single object is stored
• A special null position refers to no object.
• Positions provide a unified view of diverse ways of storing
data, such as
– a cell of an array
– a node of a linked list
• Member functions:
– Object& element(): returns the element stored at this position
– bool isNull(): returns true if this is a null position
Position ADT
• In particular, we overload the dereferencing operator (“*”), so
that, given a position variable p, the associated element can be
accessed by *p, rather than p.element().
• A position is always defined in a relative manner, that is, in
terms of its neighbors.
• Unless it is the first or last of the container, a position q is always
“after” some position p and “before” some position r
• A position q, which is associated with some element e in a
container, does not change, even if the index of e changes in the
container, unless we explicitly remove e.
• If the associated node is removed, we say that q is invalidated.
Moreover, the position q does not change even if we replace or
swap the element e stored at q with another element.
Iterators
• An iterator abstracts the process of scanning through a collection of
elements
• Extends the concept of position by adding a traversal capability
• Traversal may be in forward direction, moving to next object or in backward
direction.
• In STL Iterator typically associated with another data structure like Stack,
Queue, Vector, and other container ADTs
• Each container in STL provides two special iterator values, begin and end.
The beginning iterator refers to the first position of the container. We think
of the ending iterator as referring to an imaginary position that lies just after
the last node of the container.
• Given a container object L, the operation L.begin() returns an instance of the
beginning iterator for L, and the operation L.end() returns an instance of the
ending iterator.
List ADT
List ADT supports the following functions for a list L and
an iterator p for this list :
– begin(): Return an iterator referring to the first element
of L; same as end() if L is empty.
– end(): Return an iterator referring to an imaginary
element just after the last element of L.
– insertFront(e): Insert a new element e into L as the first
– insertBack(e): Insert a new element e into L as the last
element.
– insert(p,e): Insert a new element e into L before position
p in L.
– eraseFront(): Remove the first element of L.
– eraseBack(): Remove the last element of L.
– erase(p): Remove from L the element at position p;
invalidates p as a position.
List ADT
• An error condition occurs if an invalid
position is passed as an argument to one
of the list operations.
• Reasons for a position p to be invalid
include:
– p was never initialized or was set to a position
in a different list
– p was previously removed from the list
– p results from an illegal operation, such as
attempting to perform ++p, where p = L.end(),
that is, attempting to access a position beyond
the end position
List ADT
List ADT Applications
• A program that models several people playing a
game of cards could model each person’s hand
as a list. Since most people like to keep cards of
the same suit together, inserting and removing
cards from a person’s hand could be
implemented using the functions of the list ADT,
with the positions being determined by a natural
ordering of the suits.
• A simple text editor embeds the notion of
positional insertion and removal, since such
editors typically perform all updates relative to a
cursor, which represents the current position in
the list of characters of text being edited.
Exercise:
• Describe how to implement the following list
ADT operations using a singly-linked list
– list ADT operations: first(), last(), before(p), after(p)
– For each operation, explain how it is implemented
and provide the running time
next
• A singly linked list consists of
a sequence of nodes
• Each node stores
• element
• link to the next node elem node
head tail

Leonard Sheldon Howard Raj


Exercise:
• Describe how to implement the following list
ADT operations using a doubly-linked list
– list ADT operations: first(), last(), before(p), after(p)
– For each operation, explain how it is implemented
and provide the running time
• Doubly-Linked List Nodes
implement Position and store: prev next
• element
• link to previous node
• link to next node
elem
• Special head/tail nodes node

head tail

Leonard Sheldon Howard Raj


Performance
• In the implementation of the List ADT by
means of a doubly linked list
– The space used by a list with n elements is O(n)
– The space used by each position of the list is O(1)
– All the operations of the List ADT run in O(1) time
– Operation element() of the Position ADT runs in
O(1) time
STL list class
• vector(p,q): Construct a vector by iterating
between p and q, copying each of these elements
into the new vector.
• assign(p,q): Delete the contents of V, and assigns
its new contents by iterating between p and q
and copying each of these elements into V.
• insert(p,e): Insert a copy of e just prior to the
position given by iterator p and shifts the
subsequent elements one position to the right.
• erase(p): Remove and destroy the element of V
at the position given by p and shifts the
subsequent elements one position to the left.
• erase(p,q): Iterate between p and q, removing
and destroying all these elements and shifting
subsequent elements to the left to fill the gap.
STL list class
STL list class
Const Iterator

• In const iterator, it is possible to read the values of the


container by dereferencing the iterator, but it is not possible to
modify the container’s values.
• For example, if p is a const iterator, it is possible to read the
value of *p, but you cannot assign it a value.
• The typedef command is used to rename this lengthy definition
STL list class
Const Iterator

• In const iterator, it is possible to read the values of the


container by dereferencing the iterator, but it is not possible to
modify the container’s values.
• For example, if p is a const iterator, it is possible to read the
value of *p, but you cannot assign it a value.
• The typedef command is used to rename this lengthy definition
STL list class
• Similarities & Differences with book’s List ADT
– STL front() & back() correspond to first() & last() except the STL
functions return the element & not its position
– STL push() & pop() are equiv to List ADT insert and remove when
applied to the beginning & end of the list
– STL also provides functions for inserting & removing from
arbitrary positions in the list - these use iterators
List Summary
• List Operation Complexity for different implementations

List Singly-Linked List Doubly- Linked

first(), last(), after(p) O(1) O(1)


insertAfter(p,o),
replaceElement(p,o),
swapElements(p,q)

before(p), O(n) O(1)


insertBefore(p,o),
remove(p)
Size(), isEmpty() O(1) O(1)
Sequence ADT
• The Sequence ADT is the union of the Vector and List ADTs
• Elements accessed by
– Rank, or
– Position
• A sequence is an ADT that supports all the functions
of the list ADT but it also provides functions for
accessing elements by their index as in the vector ADT.
• The interface consists of the operations of the list ADT,
plus the following two “bridging” functions, which
provide connections between indices and positions.
– atIndex(i): Return the position of the element at
index i.
– indexOf(p): Return the index of the element at
position p.
Applications of Sequences
• The Sequence ADT is a basic, general-purpose,
data structure for storing an ordered collection of
elements
• Direct applications:
– Generic replacement for stack, queue, vector, or list
– small database (e.g., address book)
• Indirect applications:
– Building block of more complex data structures
Implementing a Sequence with a
Doubly Linked List
• In particular, if we want the functions from the list
ADT to run efficiently (using position objects to
indicate where accesses and updates should occur),
then we can no longer explicitly store the indices of
elements in the sequence.
• Hence, to perform the operation atIndex(i), we must
perform link “hopping” from one of the ends of the
list until we locate the node storing the element at
index i.
• As a slight optimization, we could start hopping from
the closest end of the sequence, which would
achieve a running time of O(min(i+1,n−i)).
Implementing a Sequence with a
Doubly Linked List
• In particular, if we want the functions from the list ADT to
run efficiently (using position objects to indicate where
accesses and updates should occur), then we can no longer
explicitly store the indices of elements in the sequence.
• Hence, to perform the operation atIndex(i), we must perform
link “hopping” from one of the ends of the list until we locate
the node storing the element at index i.
• As a slight optimization, we could start hopping from the
closest end of the sequence, which would achieve a running
time of O(min(i+1,n−i)).
• This is still O(n) in the worst case (when i is near the middle
index), but it would be more efficient in applications where
many calls to atIndex(i) are expected to involve index values
that are significantly closer to either end of the list. This is
the simple approach of walking from the front
• list,
Implementing a Sequence with a
Doubly Linked List
Exercise :
•Design a circular node list ADT that abstracts a
circularly linked list in the same way that the node
list ADT abstracts a doubly linked list.
Implementing a Sequence with a
Doubly Linked List
Implementing a Sequence with a
Doubly Linked List
Implementing a Sequence with an
Array

• instead of storing the elements of S in array A,


we store a pointer to a new kind of position
object in each cell of A.
• Each new position object p stores a pair
consisting of the index i and the element e
associated with p.
Implementing a Sequence with an
Array
Performance
Performance
• Array-based implementation is superior to the linked-list
implementation on the rank-based access operations,
atIndex and indexOf.
• It is equal in performance to the linked-list
implementation on all the other access operations.
• Regarding update operations, the linked-list
implementation beats the array-based implementation in
the position-based update operations, insert and erase.
For update operations insertFront and insertBack, the
two implementations have comparable performance.
• Considering space usage, note that an array requires
O(N) space, where N is the size of the array (unless we
utilize an extendable array), while a doubly linked list
uses O(n) space, where n is the number of elements in
the sequence. Since n is less than or equal to N, this
implies that the asymptotic space usage of a linked-list
implementation is superior to that of a fixed-size array,

You might also like