0% found this document useful (0 votes)
10 views39 pages

Unit 1

The document discusses vectors and the Vector Abstract Data Type (ADT), detailing their structure, operations, and implementations. It explains the performance of simple array-based implementations, the concept of extendable arrays, and the advantages of STL vectors, including dynamic resizing and built-in functions. Additionally, it covers various STL container types, their characteristics, and operations associated with the List ADT and iterators.

Uploaded by

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

Unit 1

The document discusses vectors and the Vector Abstract Data Type (ADT), detailing their structure, operations, and implementations. It explains the performance of simple array-based implementations, the concept of extendable arrays, and the advantages of STL vectors, including dynamic resizing and built-in functions. Additionally, it covers various STL container types, their characteristics, and operations associated with the List ADT and iterators.

Uploaded by

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

Vectors

• Suppose we have a collection S of n elements stored in a certain linear order, so that we


can refer to the elements in S as first, second, third, and so on. Such a collection is
generically referred to as a list or Sequence.
• We can uniquely refer to each element ‘e’ in S using an integer in the range [0,n − 1] that
is equal to the number of elements of S that precede ‘e’ in S.
• The index of an element e in S is the number of elements that are before e in S. Hence,
the first element in S has index 0 and the last element has index n − 1.
• Also, if an element of S has index i, its previous element (if it exists) has index i−1, and
its next element (if it exists) has index i+ 1.
• Rank is usually defined to be one more than its index. So, the first element is at rank 1,
the second is at rank 2, and so on.
• A sequence that supports access to its elements by their indices is called a vector.
The Vector Abstract Data Type
A vector, also called an array list, is an ADT that supports the following fundamental
functions (in addition to the standard size() and empty() 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 from V the element at index ‘i’; an error
condition occurs if ‘i’ is out of range.
Example
A Simple Array-Based
Implementation
An obvious choice for implementing the vector ADT is to use a fixed size array A, where A[i] stores
the element at index ‘i’.
We choose the size ‘N’ of array ‘A’ to be sufficiently large, and we maintain the number n < N of
elements in the vector in a member variable.
To implement the at(i) operation, for example, we just return A[i].
The implementations of the functions insert(i,e) and erase(i) are given in Code Fragment 6.1.

Algorithm insert(i,e):
for j = n−1,n−2,...,i do
A[ j +1] ← A[ j] {make room for the new element}
A[i] ← e
n ← n+1

Algorithm erase(i):
for j = i+1,i+2,...,n−1 do
A[ j −1] ← A[ j] {fill in for the removed element}
n ← n−1

The member variable ‘n’ stores the number of elements. An important (and time-consuming) part of
this implementation involves the shifting of elements up or down to keep the occupied cells in the
The Performance of a Simple Array-
Based Implementation
• The worst case for insert(i,e) operation occurs when i = 0, since
all the existing n elements have to be shifted forward.
• Erase(i), which runs in O(n) time, because we have to shift
backward n−1 elements in the worst case (i = 0).
• In fact, assuming that each possible index is equally likely to be
passed as an argument to these operations, their average
running time is O(n) because we have to shift n/2 elements on
average.
An Extendable Array
Implementation
• A major weakness of the simple array implementation for the vector ADT requires advance
specification of a fixed capacity, N, for the total number of elements that may be stored in the
vector.
• If the actual number of elements, n, of the vector is much smaller than N, then this
implementation will waste space.
• Worse, if n increases past N, then this implementation will crash.

• Instead, 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 This array replacement strategy
is known as an extendable array, for it can be viewed as extending the end of the underlying
array to make room for more elements.
An Extendable Array
Implementation
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).

•First Push: You add an item to the vector. Since the array has space, it just goes in. This takes
constant time, or O(1) .

•Second Push: You want to add another item, but now the array is full. So, you need to resize the
array. Usually, this means doubling the size of the array (from 1 to 2). After resizing, you copy the
existing item to the new array and then add the new item. This resizing and copying take some
extra time.

•Third Push and Onwards: As you keep adding more items, sometimes the array will fill up again,
and you'll need to double its size and copy everything over to the new array.

Total Time for All Pushes


•Although resizing is expensive when it happens, it doesn't happen with every push. In fact, it
happens less and less frequently as the array grows larger.
•The key idea is amortization: If you spread out the cost of all these resizing operations across all
the pushes, the average time per push ends up being small, specifically O(1)

•Final Result
So, even though resizing happens occasionally and can be costly, the total time for all n pushes is
Standard Template Library (STL)
STL Vectors

We refer to the type of individual elements as the vector’s base type. Each element is initialized to the base type’s
default value, which for integers is zero.
•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.)
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 Containers
The C++ Standard Template Library (STL) provides several container classes to handle collections of objects. These containers are categorized
based on their internal structure and usage patterns. Here's a summary of the main STL containers:
1. Sequence Containers
These containers store elements in a linear sequence and provide various methods for accessing and modifying them.
•std::vector:
• Description: A dynamic array that supports random access.
• Features: Fast access to elements by index, efficient appending, and removal at the end.
• Example: std::vector<int> v = {1, 2, 3};
•std::deque:
• Description: A double-ended queue that allows fast insertions and deletions at both ends.
• Features: Supports random access and efficient operations at both the front and back.
• Example: std::deque<int> d = {1, 2, 3};
•std::list:
• Description: A doubly linked list that allows bidirectional traversal.
• Features: Efficient insertions and deletions at any position, but no random access.
• Example: std::list<int> l = {1, 2, 3};
•std::forward_list:
• Description: A singly linked list that allows forward traversal.
• Features: More memory efficient than std::list but only supports forward traversal.
• Example: std::forward_list<int> fl = {1, 2, 3};
•std::array:
• Description: A fixed-size array wrapper that provides compile-time size.
• Features: Supports static allocation and efficient access, but size is fixed.
• Example: std::array<int, 3> arr = {1, 2, 3};
STL Containers
Container Adapters
These provide a different interface to underlying sequence containers.
•std::stack:
• Description: A stack (LIFO) adapter that provides push, pop, and top
operations.
• Underlying Container: Typically uses std::deque or std::vector.
• Example: std::stack<int> s; s.push(1); s.push(2);
•std::queue:
• Description: A queue (FIFO) adapter that provides enqueue and dequeue
operations.
• Underlying Container: Typically uses std::deque or std::list.
• Example: std::queue<int> q; q.push(1); q.push(2);
•std::priority_queue:
• Description: A priority queue adapter that provides access to the largest (or
smallest) element.
• Underlying Container: Typically uses std::vector and a heap structure.
• Example: std::priority_queue<int> pq; pq.push(1); pq.push(2);
Node-Based Operations and
Iterators

Node-based operations and iterators are concepts commonly associated with linked data
structures like linked lists, trees, and graphs. These structures are composed of "nodes,"
where each node contains data and references (or pointers) to other nodes.

Iterators
An iterator is an object that enables traversal through the elements of a data structure
without exposing the underlying structure details. Iterators are particularly useful for node-
based structures.
List ADT
The List Abstract Data Type (List ADT) is a fundamental data structure that represents a
collection of elements, typically in a specific order.

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 (see Figure 6.4).
Key Characteristics of the List
ADT
1.Ordered Collection: The elements in a list are ordered, meaning that each element
has a specific position (index) in the list.
2.Dynamic Size: Lists can grow or shrink dynamically as elements are added or
removed.
3.Homogeneous Elements: Typically, all elements in a list are of the same type,
though some implementations may allow mixed types.
4.Positional Access: Elements can be accessed, inserted, or removed based on their
position in the list.
Common Operations in List ADT

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 element.
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.
Implementations of List ADT
The List ADT can be implemented in various ways, each with its own trade-offs in terms of
performance for different operations.
1.Array-Based List:
1. Static Array: Fixed size, with a limit on the number of elements it can store. Operations
like get and set are O(1), while insert and remove can be O(n) due to the need to shift
elements.
2. Dynamic Array: Resizes itself when it runs out of space . Provides O(1) amortized time
for append operations, but insert and remove remain O(n) in the worst case.
2.Linked List:
1. Singly Linked List: Each node points to the next node. Insertion and deletion operations
at the beginning or end can be O(1) but accessing elements by index is O(n)
2. Doubly Linked List: Each node points to both the previous and the next node, allowing
for O(1) insertions and deletions at both ends, but still O(n) for accessing elements by
index.
3.Circular Linked List:
1. Similar to a singly or doubly linked list, but the last node points back to the first node,
forming a circle. This is useful in applications where you need to loop through the list
repeatedly.
Structure of the Doubly Linked List
•Sentinel Nodes: The list uses two sentinel nodes:
• Header: A sentinel node at the beginning of the list.
• Trailer: A sentinel node at the end of the list.
•Actual elements are inserted between the header and trailer nodes.
Key Classes and Structures
•Node: A private nested class that represents a single element (node) of the
list.
• Contains:
• Element: The data stored in the node.
• Links: Pointers to the previous and next nodes.
STD LIST

#include <list>
using std::list; // make list accessible
list<float> myList; // an empty list of floats

list(n): Construct a list with n elements; if no argument list is given, an empty


list is created.
size(): Return the number of elements in L.
empty(): Return true if L is empty and false otherwise.
front(): Return a reference to the first element of L.
back(): Return a reference to the last element of L.
push front(e): Insert a copy of e at the beginning of L.
push back(e): Insert a copy of e at the end of L.
pop front(): Remove the fist element of L.
pop back(): Remove the last element of L.
STL ITERATOR-BASED CONTAINER
FUNCTIONS
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.
clear(): Delete all these elements of V.
STL VECTORS AND ALGORITHMS

sort(p,q): Sort the elements in the range from p to q in ascending order. It is


assumed that less-than operator (“<”) is defined for the base type.
random shuffle(p,q): Rearrange the elements in the range from p to q in random
order.
reverse(p,q): Reverse the elements in the range from p to q.
find(p,q,e): Return an iterator to the first element in the range from p to q that is
equal to e; if e is not found, q is returned.
min element(p,q): Return an iterator to the minimum element in the range from p
to q.
max element(p,q): Return an iterator to the maximum element in the range from
p to q.
for each(p,q, f ): Apply the function f the elements in the range from p to q.
Feature Vectors List ADT

Contiguous block of memory Nodes allocated in memory


Memory Allocation
(dynamic array). and connected via pointers.

Dynamically expands with


Resized by copying to larger
Size Management memory allocation for
memory when full (costly).
nodes.
Random access with O(1) for Sequential access with O(n)
Access Time
indexing. for indexing.
Efficient for arbitrary
Costly if not at the end (O(n)
Insertion/Deletion positions (O(1) if pointers
due to shifting).
are known).
Minimal overhead; only Higher overhead; stores
Overhead
stores elements. elements and pointers.
For scenarios requiring For scenarios requiring
Best Use Case frequent indexing or random frequent insertions/deletions
access. at arbitrary positions.
Sequences
•Sequence: An Abstract Data Type (ADT) that generalizes the functionalities of both vector and list ADTs, allowing for
versatile data handling.
•It provides access to its elements using both indices and positions.
2. Key Characteristics
•Combines List and Vector Features:
•Supports all functions of the list ADT.
•Allows for indexed access to elements, similar to the vector ADT.
3. Sequence ADT Operations
•Basic Operations: Inherits all operations from the list ADT (e.g., insertion, deletion, traversal).
•Additional Bridging Functions:
1.atIndex(i):
•Description: Returns the position of the element located at index i.
•Purpose: Provides a way to convert an index-based access method into a position-based one.
2.indexOf(p):
•Description: Returns the index of the element at position p.
•Purpose: Converts a position-based access method back into an index-based method.
4. Advantages of Sequence ADT
•Flexibility: Offers both index-based and position-based access, making it adaptable to various use cases.
•Unified Interface: Provides a single interface for different operations, simplifying implementation and usage.
5. Applications
•Suitable for applications where both types of access (indices and positions) are beneficial, such as:
•Implementing dynamic arrays.
•Managing lists where frequent insertions and deletions are required.
Implementing a Sequence with a Doubly Linked List
1. Overview
•A sequence can be implemented using a Doubly Linked List (DLL), leveraging the strengths of both data
structures.
•This implementation allows for efficient execution of sequence functions while maintaining the functionalities of
the list ADT.
2. Function Efficiency
•List ADT Functions: Can be implemented to run in O(1) time each due to direct access via position objects.
•Sequence Functions:
•atIndex(i) and indexOf(p) can be implemented, but with less efficiency:
•atIndex(i) requires link hopping (traversing nodes) to find the node at index i.
•This operation takes O(min(i + 1, n - i)) time if starting from the closest end of the list:
•O(n) in the worst case (when i is near the middle index).
•More efficient for indices significantly closer to either end of the list.
3. Implementation Details
•The simple approach implemented starts link hopping from the front of the list, which may not be optimal but is
straightforward.
•The two-sided approach (hopping from both ends) is left as an exercise for further optimization.

Advantages of Implementation
•Dynamic Size: A doubly linked list allows the sequence to grow or shrink as needed.
•Flexible Access: Users can access elements either by position or index.
•Efficient Modifications: Insertions and deletions remain efficient due to the linked list structure.
Implementing a Sequence with an Array
1. Overview
•A sequence can be implemented by storing each element e of the sequence S in an
array A at index i.
•This approach allows for efficient indexed access to elements.
2. Position Object
•Define a position object p that holds:
• An index i representing the position of the element in the array.
• A reference to the array A.

You might also like