Design of a HashTable and its Iterators

Slides:



Advertisements
Similar presentations
Linked List 1. Introduction to Linked List 2. Node Class 3. Linked List 4. The Bag Class with Linked List.
Advertisements

Iterators & Chain Variants. Iterators  An iterator permits you to examine the elements of a data structure one at a time.  C++ iterators Input iterator.
Stacks CS-240 & CS-341 Dick Steflik. Stacks Last In, First Out operation - LIFO As items are added they are chronologically ordered, items are removed.
CSE 332: C++ Associative Containers II Associative Containers’ Associated Types Associative containers declare additional types –A key_type gives the type.
C++ / G4MICE Course Session 3 Introduction to Classes Pointers and References Makefiles Standard Template Library.
1 Hash Tables  a hash table is an array of size Tsize  has index positions 0.. Tsize-1  two types of hash tables  open hash table  array element type.
Iterators & Chain Variants. Iterators  An iterator permits you to examine the elements of a data structure one at a time.  C++ iterators Forward iterator.
HASHING Section 12.7 (P ). HASHING - have already seen binary and linear search and discussed when they might be useful (based on complexity)
1 Chapter 16-1 Linked Structures Dale/Weems. 2 Chapter 16 Topics l Meaning of a Linked List l Meaning of a Dynamic Linked List l Traversal, Insertion.
STL multimap Container. STL multimaps multimaps are associative containers –Link a key to a value –AKA: Hashtables, Associative Arrays –A multimap allows.
1. The term STL stands for ? a) Simple Template Library b) Static Template Library c) Single Type Based Library d) Standard Template Library Answer : d.
Prof. Amr Goneid, AUC1 CSCI 210 Data Structures and Algorithms Prof. Amr Goneid AUC Part 5. Dictionaries(2): Hash Tables.
1 Chapter 16 Linked Structures Dale/Weems. 2 Chapter 16 Topics l Meaning of a Linked List l Meaning of a Dynamic Linked List l Traversal, Insertion and.
Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved Stacks.
Iterator for linked-list traversal, Template & STL COMP171 Fall 2005.
ICOM 4035 – Data Structures Dr. Manuel Rodríguez Martínez Electrical and Computer Engineering Department.
1 Joe Meehean.  List of names  Set of names  Map names as keys phone #’s as values Phil Bill Will Phil Bill Will Phil Bill Will Phil: Bill:
Programming Abstractions Cynthia Lee CS106X. Topics:  Finish up heap data structure implementation › Enqueue (“bubble up”) › Dequeue (“trickle down”)
ITERATORS. Iterator An iterator in C++ is a concept that refines the iterator design pattern into a specific set of behaviors that work well with the.
Linked List Containers. Linked Lists List consists of multiple listnodes List consists of multiple listnodes Each listnode consists of Each listnode consists.
1 Associative Containers Ordered Ordered Unordered UnorderedSets Maps as sets of pairs Set API Ex: Sieve of Eratosthenes Ex: Sieve of EratosthenesImplementation.
ICOM 4035 – Data Structures Dr. Manuel Rodríguez Martínez Electrical and Computer Engineering Department.
1 Data Structures CSCI 132, Spring 2014 Lecture 33 Hash Tables.
Searching Tables Table: sequence of (key,information) pairs (key,information) pair is a record key uniquely identifies information, so no duplicate records.
1 the BSTree class  BSTreeNode has same structure as binary tree nodes  elements stored in a BSTree are a key- value pair  must be a class (or a struct)
CSCI  Sequence Containers – store sequences of values ◦ vector ◦ deque ◦ list  Associative Containers – use “keys” to access data rather than.
1 Designing Hash Tables Sections 5.3, 5.4, 5.5, 5.6.
Motivation for Generic Programming in C++
Pointers and Dynamic Arrays
Jim Fawcett CSE687 – Object Oriented Design Spring 2010
Lecture 04: Sequences structures
Design of a HashTable and its Iterators
Programming Abstractions
classes and objects review
Template Policies and Traits By Example
Linked Lists head One downside of arrays is that they have a fixed size. To solve this problem of fixed size, we’ll relax the constraint that the.
A Doubly Linked List There’s the need to access a list in reverse order prev next data dnode header 1.
LinkedList Class.
Map interface Empty() - return true if the map is empty; else return false Size() - return the number of elements in the map Find(key) - if there is an.
Hash table another data structure for implementing a map or a set
Chapter 16-2 Linked Structures
Linked Lists.
Object Oriented Programming COP3330 / CGS5409
Data structures in C++.
Chapter 3 Lists, Stacks, and Queues Abstract Data Types, Vectors
CMSC 341 Hashing 12/2/2018.
Searching Tables Table: sequence of (key,information) pairs
[Chapter 4; Chapter 6, pp ] CSC 143 Linked Lists [Chapter 4; Chapter 6, pp ]
CSE 373: Data Structures and Algorithms
CSE 373 Data Structures and Algorithms
CSE 373: Data Structures and Algorithms
Doubly Linked List Implementation
CMSC 341 Hashing 2/18/2019.
Chapter 16 Linked Structures
CISC/CMPE320 - Prof. McLeod
Pointers & Dynamic Data Structures
Jordi Cortadella and Jordi Petit Department of Computer Science
CMSC 341 Hashing 4/11/2019.
Lecture No.02 Data Structures Dr. Sohail Aslam
CMSC 341 Hashing 4/27/2019.
Data Structures and Algorithms Memory allocation and Dynamic Array
Instructor: Dr. Michael Geiger Spring 2019 Lecture 23: Exam 2 Preview
Doubly Linked List Implementation
CMSC 341 Lecture 12.
Getting queues right … finally (?)
Template Policies and Traits By Example
Some Definitions vector, string, deque, and list are standard sequence containers. set, multiset, map, multimap, unordered_set, unordered_multiset, unordered_map.
Recitation Outline Hash tables in C++ STL Examples Recursive example
Standard Template Library
Data Structures & Programming
Presentation transcript:

Design of a HashTable and its Iterators Jim Fawcett CSE687 – Object Oriented Design Spring 2007

Iterators as Smart Pointers Iterators are “smart” pointers: They provide part, or in some cases, all of the standard pointer interface: *it, it->, ++it, it++, --it, it—, … Iterators understand the underlying container structure – often they are friends of the container class:

First some notes about containers

Containers Often Must Grant Friendship To Their Iterators template < typename key, typename value, typename Hash > class HashTable { friend class HashIterator; public: typedef key key_type; typedef value value_type; typedef HashIterator< key,value,Hash > iterator; HashTable(long int size); HashTable(const HashTable<key,value,Hash>& ht); ~HashTable(); // lots more stuff here }; Starts with template parameter list. Does not use template parameters when class name is used as function name. traits Uses parameters whenever class name is used as a type.

Destructors Can Get Messy //----< helper function deletes a chain of nodes on heap >------- template < typename key, typename value, typename Hash > void HashTable< key,value,Hash >::deleteNodeChain(node<key,value>* pNode) { if(pNode == 0) return; if(pNode->next() !=0) deleteNodeChain(pNode->next()); // recursive call to walk chain delete pNode; // delete nodes on way back pNode = 0; } //----< destructor uses helper function >------------------------ HashTable< key,value,Hash >::~HashTable() for(long int i=0; i<tableSize; ++i) // delete every chain in table deleteNodeChain(table[i]);

Inserting Nodes into HashTable //----< adds key, value pair to table, returns iterator >-------- template < typename key, typename value, typename Hash > HashIterator<key,value,Hash> HashTable< key,value,Hash >::insert(const key& k, const value& v) { unsigned long loc = _hash(k); if(Contains(k)) // don't store duplicate keys Value(k) = v; // store value in current node return find(k); // return iterator pointing to current node } ++numElements; // ok, new key, so add a new node node<key,value>* pNode = new node<key,value>(k,v,table[loc]); table[loc] = pNode; return HashIterator<key,value,Hash>(*this,pNode,loc); Stores old pointer to first node in new first nodes’ successor pointer. Puts node at head of linked list of nodes, so new node is pointed to by table cell. Return iterator pointing to this new node.

Does Container Hold This Key? //----< Contains checks for containment of given key >------ template < typename key, typename value, typename Hash > bool HashTable< key,value,Hash >::Contains(const key& k) const { unsigned long loc = _hash(k); node<key,value>* pNode = table[loc]; if(pNode == 0) return false; do if(pNode->Key() == k) return true; pNode = pNode->next(); } while(pNode != 0); return false; } Contains(key) is called more often than any other function, so needs to be fast. _hash(k) gets to table address quickly. Then simple pointer operations

Find Node Containing Key //---< return iterator pointing to node with key >--- template < typename key, typename value, typename Hash > HashIterator<key,value,Hash> HashTable< key,value,Hash >::find(const key& k) { unsigned long loc = _hash.operator()(k); node<key,value>* pNode = table[loc]; if(pNode == 0) return end(); do if(pNode->Key() == k) return HashIterator<key,value,Hash>(*this,pNode); pNode = pNode->next(); } while(pNode != 0); return end(); // return iterator pointing past last element }

Copy Constructor //----< copy constructor>---------------------------------------- template < typename key, typename value, typename Hash > HashTable< key,value,Hash >::HashTable(const HashTable<key,value,Hash>& ht) : tableSize(ht.tableSize), _verbose(false) { table = new PointerToNode[tableSize]; for(long int i=0; i<tableSize; ++i) table[i] = 0; _hash.Size(tableSize); HashIterator<key,value,Hash> it; // we know we won't change ht - just reading its values // but compiler doesn't know that so we need const_cast HashIterator<key,value,Hash> itBeg = const_cast< HashTable< key,value,Hash>* >(&ht)->begin(); HashIterator<key,value,Hash> itEnd = const_cast< HashTable< key,value,Hash>* >(&ht)->end(); it = itBeg; while(it != itEnd) key k = it->Key(); value v = it->Value(); this->insert(k,v); ++it; } Here, we tell HashString function object, _hash, how big the table is. We could not do that with a function. Prefer functors over function pointers! it will point to ht Create and initial-ize table Need to use const_cast to get compiler to let us use iterator on const HashTable<…> ht Copy in ht’s values

On to Iterators What is an iterator? How do you design an iterator class? How do you integrate container and iterator?

Iterators as Smart Pointers Iterators are “smart” pointers: They provide part, or in some cases, all of the standard pointer interface: *it, it->, ++it, it++, --it, it—, … Iterators understand the underlying container structure – often they are friends of the container class:

Iterator Class traits Derives from std::iterator template <typename key, typename value, typename Hash> class HashIterator : public std::iterator< std::bidirectional_iterator_tag, node<key,value> > { public: typedef key key_type; typedef value value_type; typedef HashIterator<key,value,Hash> iterator; HashIterator(); HashIterator(const HashIterator<key,value,Hash>& hi); HashIterator( HashTable<key,value,Hash>& ht, node<key,value>* pNode = 0, long int index=0 ); HashIterator<key,value,Hash>& operator=(const HashIterator<key,value,Hash>& hi); node<key,value>& operator*(); node<key,value>* operator->(); iterator& operator++(); iterator operator++(int); iterator& operator--(); iterator operator--(int); bool operator==(const HashIterator<key,value,Hash>& hi) const; bool operator!=(const HashIterator<key,value,Hash>& hi) const; long int CurrentIndex(); private: HashTable<key,value,Hash>* pHashTable; node<key,value>* pCurrentNode; long int _CurrentIndex; }; traits Derives from std::iterator HashIterator can be constructed pointing to node. Iterator Class

Dereferencing and Selection Operations //----< de-reference operator* >--------------------------- template <typename key, typename value, typename Hash> node<key,value>& HashIterator<key,value,Hash>::operator*() { return *pCurrentNode; } //----< selection operator-> >----------------------------- node<key,value>* HashIterator<key,value,Hash>::operator->() return pCurrentNode; Supports the semantics of pointer selection, e.g.: key_type thisKey = it -> Key(); Returns pointer to node<key,value>. C++ semantics then conspire to select and execute whatever function is selected, in iterator expression, on that node.

Incrementing Operators //----< pre-increment operator++ >------------------------------- // Return iterator pointing to “next” node. // Has to walk both table and node chains. template <typename key, typename value, typename Hash> HashIterator<key,value,Hash>& HashIterator<key,value,Hash>::operator++() { if(pCurrentNode != 0 && (pCurrentNode = pCurrentNode->next()) != 0) return *this; // next node in chain if(_CurrentIndex < pHashTable->tableSize-1) long int Index = _CurrentIndex; while(pHashTable->table[++Index] == 0) if(Index == pHashTable->tableSize-1) pCurrentNode = 0; ++_CurrentIndex; return *this; // no more nodes } _CurrentIndex = Index; pCurrentNode = pHashTable->table[_CurrentIndex]; return *this; // first node in next chain _CurrentIndex = pHashTable->tableSize; return *this; In node chain, not at end. Null pointer, so no node chain here. If we get to end of table, then make iterator = end() We found a table cell with a node pointer. Should never reach this point.

Post-Increment Operation Supports the syntax: (it++) -> Value(); //----< post-increment operator++ >------------------- template <typename key, typename value, typename Hash> HashIterator<key,value,Hash> HashIterator<key,value,Hash>::operator++(int) { HashIterator<key,value,Hash> temp(*this); // save current iterator operator++(); // increment internal state return temp; // return temp of prior state } Post increment and post decrement operators require making temporary iterator objects – what’s returned, as well as doing all the work associated with incrementing.

//----< default constructor >------------------------------------ template <typename key, typename value, typename Hash> HashIterator<key,value,Hash>::HashIterator() : pHashTable(0), pCurrentNode(0) {} //----< copy constructor >--------------------------------------- HashIterator<key,value,Hash>:: HashIterator(const HashIterator<key,value,Hash>& hi) { pHashTable = hi.pHashTable; // iterator pointing to same table pCurrentNode = hi.pCurrentNode; _CurrentIndex = hi._CurrentIndex; } //----< ctor takes a HashTable, pointer to node, and index >----- // used only in find(), begin(), and end() HashIterator( HashTable<key,value,Hash>& ht, node<key,value>* pNode, long int index ) : pHashTable(&ht), pCurrentNode(pNode), _CurrentIndex(index) {} Constructors

End of Containers and Iterators Monday’s fairly small and simple HashTable has grown some, partly to provide a standard container interface (like the STL containers), but mostly to support iteration over container elements. Iterator is best thought of as a smart pointer that knows about the container class and is attached to it through friendship and through many instances of creation by the HashTable container: HashTable<key,value,Hash>::find(key) and insert(key,value) functions return iterators pointing to the found or inserted node.

End of Presentation