Back

Dictionary ADT

Definition

A Dictionary Abstract Data Type (ADT) is a data structure that stores data as key-value pairs, where each key uniquely identifies its associated value.

A dictionary supports operations such as insert, remove, find, and update. It is commonly used in databases, search engines, compilers, and caching systems.


Key Points

  • A dictionary stores key-value pairs.

  • Keys are unique, while values may be duplicated.

  • Common operations include:

    • Insert(key, value)
    • Remove(key)
    • Find(key)
    • Update(key, value)
  • Dictionaries can be implemented using:

    • Arrays
    • Linked lists
    • Vectors
    • Hash tables
    • Trees
  • A simple dictionary implementation using a vector performs linear search, resulting in O(n) search time.

  • Hash-table implementations can provide O(1) average search time.

  • A location-aware dictionary also tracks the index or location of each entry.

Example

KeyValue
"ID101""Ali"
"ID102""Sara"
"ID103""Khan"

Example / Code

Simple Dictionary in C++

#include <iostream>
#include <vector>
#include <string>
using namespace std;

template <typename K, typename V>
class Dictionary {
private:
    vector<pair<K, V>> data;

public:
    void insert(K key, V value) {
        for (auto &item : data) {
            if (item.first == key) {
                item.second = value; // update existing value
                return;
            }
        }

        data.push_back({key, value});
    }

    bool find(K key, V &value) {
        for (auto &item : data) {
            if (item.first == key) {
                value = item.second;
                return true;
            }
        }

        return false;
    }

    void remove(K key) {
        for (auto it = data.begin(); it != data.end(); it++) {
            if (it->first == key) {
                data.erase(it);
                return;
            }
        }
    }

    void display() {
        for (auto &item : data) {
            cout << item.first << " -> " << item.second << endl;
        }
    }
};

int main() {
    Dictionary<int, string> dict;

    dict.insert(1, "Ali");
    dict.insert(2, "Sara");
    dict.insert(3, "Omar");

    cout << "Dictionary contents:\n";
    dict.display();

    string value;

    if (dict.find(2, value))
        cout << "\nFound: " << value << endl;

    dict.remove(1);

    cout << "\nAfter deletion:\n";
    dict.display();

    return 0;
}

Code Explanation

1. Template Declaration

template <typename K, typename V>
  • Makes the dictionary generic.
  • K represents the key type.
  • V represents the value type.

For example:

Dictionary<int, string>

means the keys are integers and the values are strings.

2. Data Storage

vector<pair<K, V>> data;
  • Stores key-value pairs inside a vector.
  • pair<K, V> contains one key and its corresponding value.

3. Insert Operation

void insert(K key, V value)
  • Searches for the key first.
  • If the key already exists, its value is updated.
  • Otherwise, a new key-value pair is added.
item.second = value;

updates the existing value.

data.push_back({key, value});

adds a new pair.

4. Find Operation

bool find(K key, V &value)
  • Searches through the vector.
  • If the key is found, its value is stored in value.
  • Returns true when found and false otherwise.

5. Remove Operation

data.erase(it);

Removes the key-value pair corresponding to the requested key.

6. Display Operation

cout << item.first << " -> " << item.second << endl;

Prints each key and its associated value.


Explanation

1. Dictionary Operations

OperationPurpose
InsertAdds a key-value pair
FindSearches for a key and retrieves its value
UpdateChanges the value associated with a key
RemoveDeletes a key-value pair
DisplayShows stored entries

2. Why Keys Must Be Unique

Each key identifies a particular entry.

For example:

101 → Ali
102 → Sara

If the same key is inserted again:

101 → Omar

the simple implementation updates the existing value rather than creating another entry with key 101.

Therefore:

Keys uniquely identify dictionary entries.

Values, however, may be repeated.

101 → Ali
102 → Ali

is valid because the keys are different.


3. Dictionary as an ADT

A dictionary is an Abstract Data Type because it defines what operations are available without requiring a specific implementation.

For example, a dictionary may be implemented using:

  • A vector
  • An array
  • A linked list
  • A binary search tree
  • A hash table

The interface remains conceptually the same even when the underlying implementation changes.


4. Simple Dictionary Complexity

The provided implementation stores entries in a vector and searches sequentially.

OperationTime Complexity
InsertO(n)
SearchO(n)
DeleteO(n)

The linear complexity occurs because the implementation may need to examine every entry.

Why Is Linear Search Used?

The simple implementation uses linear search because it is:

  • Easy to understand
  • Easy to implement
  • Suitable for educational purposes
  • Appropriate for small datasets

For large datasets, more advanced implementations such as hash tables or balanced trees are preferred.


Location-Aware Dictionary

Definition

A location-aware dictionary stores key-value pairs while also tracking the position or index of each entry.

Example:

KeyValueLocation
A1000
B2001
C3002

The location can represent an index in an array or vector.

Why Location Awareness?

Location information can be useful for:

  • Tracking entries
  • Faster updates in some systems
  • Efficient deletion strategies
  • Symbol tables
  • File indexing
  • Database-related systems

C++ Implementation

#include <iostream>
#include <vector>
using namespace std;

template <typename K, typename V>
class LocationAwareDictionary {
private:
    vector<pair<K, V>> data;

public:
    void insert(K key, V value) {
        data.push_back({key, value});
    }

    void showLocations() {
        for (int i = 0; i < data.size(); i++) {
            cout << "Key: " << data[i].first
                 << " Value: " << data[i].second
                 << " Location: " << i << endl;
        }
    }

    int getLocation(K key) {
        for (int i = 0; i < data.size(); i++) {
            if (data[i].first == key)
                return i;
        }

        return -1;
    }
};

Important Functions

insert()

data.push_back({key, value});

Adds a new key-value pair to the vector.

showLocations()

for (int i = 0; i < data.size(); i++)

Traverses the vector and displays the index of every entry.

getLocation()

if (data[i].first == key)
    return i;

Searches for a key and returns its index.

If the key does not exist:

return -1;

indicates that the key was not found.


Dictionary Implementations

ImplementationTypical SearchMain Characteristic
Array/VectorO(n)Simple
Linked ListO(n)Dynamic nodes
Balanced Search TreeO(log n)Maintains ordered keys
Hash TableO(1) averageVery fast average lookup

The actual performance depends on the implementation and its design.


Dictionary vs. Map ADT

A Dictionary ADT and Map ADT are closely related concepts. Both organize information using key-value relationships.

FeatureDictionary ADTMap ADT
StoresKey-value pairsKey-value pairs
Unique keysYesYes
Main purposeKey-based retrievalKey-based association
Possible implementationsLists, trees, hashingLists, trees, hashing
AbstractionDefines dictionary operationsDefines map operations

In many programming contexts, the terms dictionary and map are used interchangeably.


Real-World Applications

Dictionaries are widely used in:

  • Databases — associating identifiers with records
  • Compilers — symbol tables associate identifiers with information
  • Search engines — mapping terms to indexed information
  • Caching systems — associating keys with stored data
  • Programming languages — implementing associative collections

In C++, related standard-library containers include:

  • std::map — ordered key-value container
  • std::unordered_map — hash-table-based key-value container

Output (if any)

For the simple dictionary example, the output is conceptually:

Dictionary contents:
1 -> Ali
2 -> Sara
3 -> Omar

Found: Sara

After deletion:
2 -> Sara
3 -> Omar

Common Mistakes

  • Allowing duplicate keys: A dictionary requires keys to be unique.
  • Confusing keys and values: The key identifies an entry; the value is the associated data.
  • Assuming all dictionaries have O(1) search: Complexity depends on the implementation.
  • Confusing ADT with implementation: The Dictionary ADT defines operations, while a vector, tree, or hash table provides the implementation.
  • Forgetting the not-found case: Search functions should indicate when a key does not exist.
  • Assuming location is permanent: In a vector-based structure, inserting or deleting elements can change indices.
  • Using linear search for very large datasets: Hash tables or balanced trees are generally more appropriate for large collections.

Short Exam Notes

  • Dictionary ADT: Stores data as unique key-value pairs.
  • Main operations: Insert, Find, Update, Remove.
  • Keys: Must be unique.
  • Values: May be duplicated.
  • Simple vector-based dictionary: Uses linear search.
  • Simple implementation complexity: Insert, Search, and Delete are generally O(n).
  • Location-aware dictionary: Tracks the index/location of entries.
  • Hash-table dictionary: Provides O(1) average lookup.
  • Tree-based dictionary: Can provide O(log n) search when balanced.
  • Applications: Databases, compilers, search engines, and caching.
  • C++ containers: std::map and std::unordered_map.