0% found this document useful (0 votes)
83 views

Data Structures AND Algorithms: Lecture Notes 6

This document discusses sequential containers and algorithms in computer engineering. It covers topics like single-linked lists, double-linked lists, list classes, standard library containers, and iterators. Specifically, it provides code examples for implementing list nodes, inserting and removing nodes from single and double linked lists, and using iterators to traverse list elements in a loop.

Uploaded by

elemaniaq
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
83 views

Data Structures AND Algorithms: Lecture Notes 6

This document discusses sequential containers and algorithms in computer engineering. It covers topics like single-linked lists, double-linked lists, list classes, standard library containers, and iterators. Specifically, it provides code examples for implementing list nodes, inserting and removing nodes from single and double linked lists, and using iterators to traverse list elements in a loop.

Uploaded by

elemaniaq
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 51

Bilgisayar Mühendisliği Bölümü

DATA STRUCTURES
AND
ALGORITHMS

Lecture Notes 6
Sequential Containers

Spring 2008

GIT – Computer Engineering Department


ROAD MAP
 Single-Linked Lists and Double-Linked Lists
 The list class and the Iterator
 Implementation of a Double-Linked List Class
 Applications of the list Class
 Standard Library Containers
 Standard Library Algorithms and Function
Objects

GIT – Computer Engineering Department Simulation - Lecture Notes 6 2


Array based Vector
 Using simple arrays
– Need to define an array size
• Allows the array to grow
• Overestimate (waste of space)

 Index operator : O(1)


 Inserting or removing general elements : O(n)
 Inserting or removing at end (usually) : O(1)
– With our reallocation policy the average is O(1)
– The worst case is O(n) because of reallocation
 Searching an element : O(n)

GIT – Computer Engineering Department Simulation - Lecture Notes 6 3


Singly-Linked Lists and Doubly-Linked Lists

 Linked list improves insertion:


– Add/remove items anywhere in constant time: O(1)
 Each element (node) in a linked list stores:
– The element information, of type Item_Type
– A link to the next node
– A link to the previous node (optional)

GIT – Computer Engineering Department Simulation - Lecture Notes 6 4


A List Node
 A node contains:
– A data item
– One or more links
 A link is a pointer to a list node
 The node class is usually defined inside
another class:
– It is a hidden inner class
– The details of a node should be kept private

GIT – Computer Engineering Department Simulation - Lecture Notes 6 5


List Nodes for Singly-Linked Lists
 Series of nodes
– not adjacent in memory
– contain the element and a pointer to a node containing its succesor
 Avoids the linear cost of insertion and deletion !

GIT – Computer Engineering Department Simulation - Lecture Notes 6 6


List Nodes for Singly-Linked Lists
#ifndef NODE_H_
#define NODE_H_

/** A Node is the building block for a single-


single-linked list. */
struct Node {
// Data Fields
/** The data */
Item_Type data;
/** The pointer to the next node. */
Node* next;

// Constructor
/** Creates a new Node that points to another Node.
@param data_item The data stored
@param next_ptr pointer to the Node that is
pointed to by the new Node
*/
Node(const Item_Type&
Item_Type& data_item,
data_item, Node* next_ptr = NULL) :
data(data_item),
data(data_item), next(next_ptr)
next(next_ptr) {}
};
#endif

GIT – Computer Engineering Department Simulation - Lecture Notes 6 7


struct versus class
 A struct is the same as a class.
– Except that the default visibility for a struct is
public.
public
 Generally structs
struct are used to define
classes that only contain public data fields.
– Constructors may be provided.
– Other member functions (operators) are usually
not defined for structs.
struct

GIT – Computer Engineering Department Simulation - Lecture Notes 6 8


Inserting a Node into a Single Linked List

Node* bob = new Node("Bob");


bob->next = harry->next; // step 1
harry->next = bob; // step 2

GIT – Computer Engineering Department Simulation - Lecture Notes 6 9


Removing a node from a single-linked list

Node* ptr = tom->next;


tom->next = tom->next->next;
delete ptr;

GIT – Computer Engineering Department Simulation - Lecture Notes 6 10


Single Linked List
 Need to know where the first node is
– the rest of the nodes can be accessed
 No need to move some part of the list for
insertion and deletion operations
 No memory waste

GIT – Computer Engineering Department Simulation - Lecture Notes 6 11


Doubly-Linked Lists
 Limitations of a singly-linked list include:
– Can insert only after a referenced node
– Removing node requires pointer to previous node
– Can traverse list only in the forward direction
• Traversing list backwards?
 We can remove these limitations:
– Add a pointer in each node to the previous node:
doubly-linked list

GIT – Computer Engineering Department Simulation - Lecture Notes 6 12


Doubly-Linked Lists, The Diagrams

GIT – Computer Engineering Department Simulation - Lecture Notes 6 13


Inserting into a Double-Linked List

DNode* sharon = new DNode("Sharon");


// Link new DNode to its neighbors
sharon->next = sam; // Step 1
sharon->prev = sam->prev; // Step 2

GIT – Computer Engineering Department Simulation - Lecture Notes 6 14


Inserting into a Double-Linked List

// Link old predicessor of sam to new predicessor.


sam->prev->next = sharon; // Step 3
// Link to new predicessor.
sam->prev = sharon; // Step 4

GIT – Computer Engineering Department Simulation - Lecture Notes 6 15


Removal from a Double-Linked List

harry->prev->next = harry->next; // Step 1


harry->next->prev = harry->prev; // Step 2
delete harry;

Insertion and deletion more pointer fixing

GIT – Computer Engineering Department Simulation - Lecture Notes 6 16


Circular Lists
 Circular doubly-linked list:
– Link last node to the first node, and
– Link first node to the last
 Advantages:
– Can easily keep going “past” ends
– Can visit all elements from any starting point
– Can never fall off the end of a list
 Disadvantage: code must avoid infinite loop!
 Can also build singly-linked circular lists:
– Traverse in forward direction only
GIT – Computer Engineering Department Simulation - Lecture Notes 6 17
Implementing a Circular List

GIT – Computer Engineering Department Simulation - Lecture Notes 6 18


Linked List based Vector
 It is possible to implement the vector using linked list
 What about performance?
Array Linked List
– Index operator : O(1) O(n)
– Insert or remove in general : O(n) O(n)
– Insert or remove at end : O(1) O(1)
– Searching an element : O(n) O(n)

 Do not benefit from all the advantages of linked list.


 Change the ADT : List ADT

GIT – Computer Engineering Department Simulation - Lecture Notes 6 19


List ADT
 List is another sequential container
 Provides following operations
– insert
• Insert after a known position
– remove
• Remove an element with known position
– push_back
– push_front
– pop_back
– pop_front
– swap
– empty
– size

GIT – Computer Engineering Department Simulation - Lecture Notes 6 20


The iterator
 Suppose we want to access each element of a list in
a loop:
for (Item_Type index = 0; index < a_list.size(); index++) {
// Do something with next_element, the element
// at position index
Item_Type next_element = a_list[index]; // not valid
}

 The subscripting operator (operator[]) is not


defined for the list ADT.
 Instead an iterator is used to access elements in a
list.

GIT – Computer Engineering Department Simulation - Lecture Notes 6 21


The iterator (2)

GIT – Computer Engineering Department Simulation - Lecture Notes 6 22


Using an Iterator
 We use an iterator like a pointer.
// Access each list element and process it
for (list<Item_Type>::iterator iter = a_list.begin();
iter != a_list.end(); ++iter) {
// Do something with next element (*iter)
Item_Type next_element = *iter;
. . .
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 23


Notes on using iterators in loops
 We test for the end of the loop with the expression:
iter != a_list.end()
The order of individual iterator values is not
meaningful.
Thus iter < a_list.end() is not a meaningful test.
 We increment the iterator using the expression
++iter;
The postfix increment operator saves the previous
value and then performs the increment.
Since this previous value is not used, it is more
efficient to use the prefix increment operator.

GIT – Computer Engineering Department Simulation - Lecture Notes 6 24


iterator versus const_iterator
 Each standard library container (e.g. the list)
provides both an
iterator
 and a
const_iterator
 The operations on them are the same, except
 When a const_iterator is dereferenced
(operator*), the value of the item
referenced cannot be changed.

GIT – Computer Engineering Department Simulation - Lecture Notes 6 25


Iterator Hierarchy

GIT – Computer Engineering Department Simulation - Lecture Notes 6 26


Iterator Functions
Function Behavior Required for Iterator Type
const Item_Type& operator* Returns a reference to the object All except output_iterator
referenced by the current iterator
position that can be used on the right-
hand side of an assignment.
Item_Type& operator* Returns a reference to the object All except input_iterator.
referenced by the current iterator
position that can be used on the left-
hand side of an assignment.
iterator& operator++() Prefix increment operator. All iterators.
iterator operator++(int) Postfix increment operator All iterators
iterator& operator--() Prefix decrement operator bidirectional_iterator and
random_access_iterator
iterator operator--(int) Postfix decrement operator bidirectional_iterator and
random_access_iterator
iterator& operator+=(int) Addition-assignment operator random_access_iterator
iterator operator+(int) Addition operator random_access_iterator
iterator& operator-=(int) Subtraction-assignment operator random_access_iterator
iterator operator-(int) Subtraction operator random_access_iterator
int operator- Subtraction of two iterators random_access_iterator
(random_access_iterator,
random_access_iterator)

GIT – Computer Engineering Department Simulation - Lecture Notes 6 27


The list ADT
 Part of the C++ Standard Library
Function Behavior
iterator insert(iterator pos, const Item_Type& Inserts a copy of item into the list at position pos. Returns an
item)
iterator that references the newly inserted item.
iterator erase(iterator pos) Removes the item from the list at position pos. Returns an
iterator that references the item following the one erased.
void remove(const Item_Type& item) Removes all occurrences of item from the list.
void push_front(const Item_Type& item) Inserts a copy of item as the first element of the list.
void push_back(const Item_Type& item) Adds a copy of item to the end of the list.
void pop_front() Removes the first item from the list.
void pop_back() Removes the last item from the list.
Item_Type& front(); Gets the first element in the list. Both constant and modifiable
const Item_Type& front() const
versions are provided.
Item_Type& back(); Gets the last element in the list. Both constant and modifiable
const Item_Type& back() const
versions are provided.
iterator begin() Returns an iterator that references the first item of the list.
const_iterator() begin const Returns a const_iterator that references the first item of
the list.
iterator end() Returns an iterator that references the end of the list (one
past the last item).
const_iterator end() const Returns a const_iterator that references the end of the list
(one past the last item).
void swap(list<Item_Type>& other) Exchanges the contents of this list with the other list.
bool empty() const Returns true if the list is empty.
size_t size() const Returns the number of items in the list.

GIT – Computer Engineering Department Simulation - Lecture Notes 6 28


Implementing KW::list
template<typename
template<typename Item_Type>
Item_Type>
class list {
private:
// Insert definition of nested class DNode here.
#include "DNode.h
"DNode.h"
DNode.h"
public:
// Insert definition of nested class iterator here.
#include "list_iterator.h
"list_iterator.h"
list_iterator.h"
// Give iterator access to private members of list.
friend class iterator;
iterator;
// Insert definition of nested class const_iterator here.
#include "list_const_iterator.h
"list_const_iterator.h"
list_const_iterator.h"
// Give const_iterator access to private members of list.
friend class const_iterator;
const_iterator;
private:
// Data fields
/** A reference to the head of the list */
DNode*
DNode* head;
/** A reference to the end of the list */
DNode*
DNode* tail;
/** The size of the list */
size_t num_items;
num_items;
GIT – Computer Engineering Department Simulation - Lecture Notes 6 29
List Nodes for Doubly-Linked Lists
#ifndef NODE_H_
#define NODE_H_

/** A Node is the building block for a single-


single-linked list. */
struct Node {
// Data Fields
/** The data */
Item_Type data;
/** The pointer to the next node. */
Node* next;
/** The pointer to the prev node. */
Node* prev;
prev;

// Constructor
/** Creates a new Node that points to another Node.
@param data_item The data stored
@param next_ptr pointer to the Node that is
pointed to by the new Node
*/
Node(const Item_Type&
Item_Type& data_item,
data_item,
Node* next_ptr = NULL Node* prev_ptr = NULL) :
data(data_item),
data(data_item), next(next_ptr),
next(next_ptr), perv(prev_ptr)
perv(prev_ptr) {}
};
#endif

GIT – Computer Engineering Department Simulation - Lecture Notes 6 30


The no-argument constructor

/** Construct an empty list. */


list() : head(NULL), tail(NULL), num_items(0)
{ }

GIT – Computer Engineering Department Simulation - Lecture Notes 6 31


The Copy Constructor

/** Construct a copy of a list. */


list(const list<Item_Type>& other) list() : head(NULL),
tail(NULL), num_items(0) {
for (const_iterator itr = other.begin();
itr != other.end(); ++itr) {
push_back(*itr);
}
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 32


The Destructor
/** Destroy a list. */
~list() {
while (head != NULL) {
DNode* current = head;
head = head->next;
delete current;
}
tail = NULL;
num_items = 0;
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 33


The Assignment Operator
/** Assign the contents of one list to another. */
list<Item_Type>& operator=(const list<Item_Type>& other)
{
// Make a copy of the other list.
list<Item_Type> temp_copy(other);
// Swap contents of self with the copy.
swap(temp_copy);
// Return -- upon return the old value will be destroyed.
return *this;
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 34


The push_front function

void push_front(const Item_Type& item) {


head = new DNode(item, NULL, head); // Step 1
if (head->next != NULL)
head->next->prev = head; // Step 2
if (tail == NULL) // List was empty.
tail = head;
num_items++;
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 35


Adding to the Head of the list

GIT – Computer Engineering Department Simulation - Lecture Notes 6 36


The push_back function
void push_back(const Item_Type& item) {
if (tail != NULL) {
tail->next = new DNode(item, tail, NULL); // Step 1
tail = tail->next; // Step 2
num_items++;
} else { // List was empty.
push_front(item);
}
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 37


Adding to the Tail of the list

GIT – Computer Engineering Department Simulation - Lecture Notes 6 38


The insert function
iterator insert(iterator pos, const Item_Type& item) {
// Check for special cases
if (pos.current == head) {
push_front(item);
return begin();
} else if (pos.current == NULL) { // Past the last node.
push_back(item);
return iterator(this,tail);
}
// Create a new node linked before node referenced by pos.
DNode* new_node = new DNode(item,
pos.current->prev,
pos.current); // Step 1
// Update links
pos.current->prev->next = new_node; // Step 2
pos.current->prev = new_node; // Step 3
num_items++;
return iterator(this, new_node);
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 39


Adding to the Middle of the list

GIT – Computer Engineering Department Simulation - Lecture Notes 6 40


The pop_front Function
void pop_front() {
if (head == NULL)
throw std::invalid_argument
("Attempt to call pop_front() on an empty list");
DNode* removed_node = head;
head = head->next;
delete removed_node;
if (head != NULL)
head->prev = NULL;
else
tail = NULL;
num_items--;
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 41


The pop_back Function
void pop_back() {
if (tail == NULL)
throw std::invalid_argument
("Attempt to call pop_back() on an empty list");
DNode* removed_node = tail;
tail = tail->prev;
delete removed_node;
if (tail != NULL)
tail->next = NULL;
else
head = NULL;
num_items--;
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 42


The erase Function
iterator erase(iterator pos) {
if (empty())
throw std::invalid_argument ("Attempt to call erase on an empty list");
if (pos == end())
throw std::invalid_argument ("Attempt to call erase of end()");
// Create an iterator that references the position following pos.
iterator return_value = pos;
++return_value
++return_value;
return_value;
// Check for special cases.
if (pos.current
(pos.current == head) {
pop_front();
pop_front();
return return_value;
return_value;
} else if (pos.current
(pos.current == tail) {
pop_back();
pop_back();
return return_value;
return_value;
} else { // Remove a node in the Item_Typeerior of the list.
// Unlink current node.
DNode*
DNode* removed_node = pos.current;
pos.current;
removed_node-
removed_node->prev-
prev->next = removed_node-
removed_node->next;
removed_node-
removed_node->next-
>next->prev = removed_node-
removed_node->prev;
prev;
delete removed_node;
removed_node;
return return_value;
return_value;
}
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 43


The kw::list<Item_Type>::iterator
Data Field Attribute
DNode* current A pointer to the current item.
A pointer to the list of which this iterator
list<Item_Type>* parent
is a member.

GIT – Computer Engineering Department Simulation - Lecture Notes 6 44


Data Fields and The Constructor
class iterator {
// Give the parent class access to this class.
friend class list<Item_Type
list<Item_Type>;
Item_Type>;
private:
// Data fields
/** A reference to the parent list */
list<Item_Type
list<Item_Type>*
Item_Type>* parent;
/** A pointer to the current DNode */
typename list<Item_Type
list<Item_Type>::
Item_Type>::DNode
>::DNode*
DNode* current;
// Member functions
/** Constructs an iterator that references a specific DNode.
DNode.
Note: this constructor is private. Only the list class
can create one from scratch.
@param my_parent A reference to the list
@param position A pointer to the current DNode
*/
iterator(list<
iterator(list<Item_Type>*
Item_Type>* my_parent,
my_parent, DNode*
DNode* position) :
parent(my_parent),
parent(my_parent), current(position)
current(position) {}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 45


Dereferencing Operators
/** Returns a reference to the currently referenced item.
@return A reference to the currently referenced item
@throws std::invalid_argument if this iterator is at end
*/
Item_Type&
Item_Type& operator*() const {
if (current == NULL)
throw std::invalid_argument("Attempt to dereference end()");
return current-
current->data;
}

/** Returns a pointer to the currently referenced item.


Item_Type must be a class or struct.
struct. This restriction
is enforced by the compiler.
@return A pointer to the currently referenced item
@throws std::invalid_argument If this iterator is at end
*/
Item_Type*
Item_Type* operator-
operator->() const {
if (current == NULL)
throw std::invalid_argument("Attempt to dereference end()");
return &(current-
&(current->data);
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 46


Prefix increment and decrement
iterator&
iterator& operator++() {
/*<snippet id="5" omit="false">*/
if (current == NULL)
throw std::invalid_argument("Attempt to advance past end()");
current = current-
current->next;
return *this;
}

iterator&
iterator& operator--
operator--()
--() {
if (current == parent-
parent->head)
throw std::invalid_argument("Attempt to move before begin()");
if (current == NULL) // Past last element.
current = parent-
parent->tail;
else
current = current-
current->prev;
prev;
return *this;
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 47


Postfix increment and decrement
iterator operator++(Item_Type)
operator++(Item_Type) {
// Make a copy of the current value.
iterator return_value = *this;
// Advance self forward.
++(*this);
// Return old value.
return return_value;
return_value; // Return the value prior to increment
}

iterator operator--
operator--(
--(Item_Type)
Item_Type) {
// Make a copy of the current value.
iterator return_value = *this;
// Move self backward.
--(*this);
--(*this);
// Return old value.
return return_value;
return_value; // Return the value prior to decrement
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 48


The const_iterator
 Identical to the iterator except that the dereferencing
operators are defined as follows:

const Item_Type& operator*() const {


if (current == NULL)
throw std::invalid_argument
("Attempt to dereference end()");
return current->data;
}

const Item_Type* operator->() const {


if (current == NULL)
throw std::invalid_argument
("Attempt to dereference end()");
return &(current->data);
}

GIT – Computer Engineering Department Simulation - Lecture Notes 6 49


Cursor Implementation of Linked List
Problems with linked list implementation:
 Same language do not support pointers !
– Then how can you use linked lists ?
 new and delete operations are slow
– Actually not constant time

GIT – Computer Engineering Department Simulation - Lecture Notes 6 50


Linked List Implementation of Lists

Linked List Array


PrintList O(N) (traverse the list) O(N)
Find

FindKth (L,i) O(i) O(1)

Delete O(1) O(N)


Insert

GIT – Computer Engineering Department Simulation - Lecture Notes 6 51

You might also like