TrieContact: A Contact Book Built Like an Autocomplete Engine

How a dual-trie C++ design turns names and numbers into two different search problems, then stores each one for the fastest possible lookup.

7 min read • View on GitHub • More from tusharb-25

A terminal prompt branches into two very different search paths. One side blooms into a tangled tree of mixed letters for names, while the other becomes a clean ten-lane corridor for phone digits. The image explains that TrieContact treats names and numbers as separate lookup problems.
TrieContact’s core idea is visible in one glance: the same contact input feeds two search structures tuned to two different kinds of data.
Key Takeaways

What Kind of Contact Book Is This?

TrieContact is not really a contact book in the usual sense. It is a prefix engine that happens to store contacts. That difference matters, because the whole system is organized around the question, what should happen the moment a user starts typing?

Most contact apps optimize for exact retrieval. TrieContact optimizes for the first few characters. That pushes the design toward tries, autocomplete, and instant suggestions instead of the more familiar database or hash-map approach.

Two hands index the same contact card into parallel storage. One hand feeds letters into a branching name structure, while the other places digits into a numbered rack. The image explains why insertion in TrieContact updates multiple indexes at once.
Insertion is not a single write. TrieContact copies one contact into multiple indexes so search stays fast from both directions.

Why Two Tries, Not One

This is the project’s best idea. Names and phone numbers look similar at the UI layer, but they are different search domains. Names need flexibility. Phone numbers need strict, tiny branching over a fixed alphabet of ten digits.

The architecture is a split-brain system by design. One index is optimized for character richness, the other for the speed of digit traversal.

ApproachPrefix searchExact lookupMemory footprintComplexity
Flat listSlow linear scanSlow linear scanLowVery low
Hash mapPoor for prefixesFastModerateLow
Single generic trieFastNeeds extra plumbingModerate to highModerate
TrieContactFast for names and numbersFast through mapsHighHigher

The name trie and the number trie solve different problems

The name trie uses a map-backed child set, which gives it flexibility for richer character input. That choice is slower than a fixed array, but it avoids baking in a narrow alphabet. The number trie uses a 10-way array, which is exactly what digits want.

That asymmetry is the point. TrieContact does not insist on one elegant abstraction for both fields. It picks the structure that fits each data type, then keeps them synchronized.

struct triename {
    map<char, struct triename*> namechild;
    int isleaf;
};

struct trienum {
    struct trienum* numchild[10];
    int isleaf;
};

void insertcontact(string& name, string& number) {
    // write into both tries and both maps
}

Inside the Insert Path

Insertion is where the design becomes concrete. One contact is written into the name trie, the number trie, and the exact-lookup maps that bridge them. That means every contact exists in multiple places for different kinds of queries.

This is why the repo feels more like a search system than a notebook. A single write creates several lookup paths, and each path is optimized for a different user intent: prefix completion, exact match, or reverse lookup.

Lookup needBest structure in TrieContactWhy it wins
Name prefixName trieFlexible branching supports richer character sets
Number prefixNumber trieTen fixed children give predictable digit traversal
Exact name to numbernametonum mapDirect access without walking a trie
Exact number to namenumtoname mapInverse lookup is immediate

The Memory Trade-Off Nobody Can Ignore

Speed is not free here. The project stores the same contact in two tries and two maps, so memory cost rises fast. That is the bargain TrieContact makes in exchange for instant-feeling search.

For a small contact manager, that trade-off is reasonable. For a huge address book, it would start to hurt. The design is honest about its priorities: responsiveness first, compactness second.

What the Repo Says About Its Builder

The codebase looks like a compact C++ project built in a competitive-programming or student workflow. A single source file, <bits/stdc++.h>, and a bundled Windows executable all point to a builder who values directness over ceremony.

That context helps explain the shape of the project. It is not trying to be a polished platform. It is trying to prove an idea clearly: if you treat contact lookup like search, the data structure changes with it.

The Bottom Line

TrieContact is a neat reminder that product thinking starts with behavior, not storage. If users want autocomplete, build for autocomplete. If names and numbers behave differently, do not force them through the same pipe.

The repo’s real value is conceptual. It shows how a small CLI tool can still have a sharp architecture when the data model mirrors the user’s query model.