How would you store the contacts in an android phone if the “contact searching while typing” has to be fast and a contact can have multiple phone numbers.
I think Trie Tree will be best. At the end of the character of the name, you can store an object with its elements like an array of the phone number, email variable, and some extra variable that you want.
when searching a name you can go through the character in Trie Tree and show at least n name in sorted order. I think Trie tree will be faster than any other data structure.
You can use a standard TreeMap<String, Contact> to implement this feature (where Contact would be a class storing the phone numbers etc). One option is to use TreeMap.tailMap() to get a sub-map of the entries starting from what the user has typed so far (backed by the original map, so this should be fast). You can use a custom comparator to adjust the ordering to your needs (e.g. case-insensitive)
p.s.: That doesn't address persistence, so you may want to use a database from the start, e.g. Room. Prefix search tyically can be implemented by searching for the range (prefix, prefix + "\uffff"). With databases, one would typically add a limit.
Related
How can I use a trie (or another data structure or algorithm) to efficiently search for multiple words by prefix?
For example: suppose this is my data set:
Alice Jones
Bob Smith
Bobby Walker
John Doe
(10000 names in total)
A trie data structure allows me to efficiently retrieve all names starting with "Bo" (thus without iterating over all the names). But I also want to search on the last name by prefix, thus searching for "Wa" should find "Bobby Walker". And to complicate things: when the user searches for "Bo Wa" this should also find the same name. How can I implement this? Should I use a separate trie structure for each part of the name? (And how to combine the results)?
Background: I'm writing the search functionality for a big address book (10000+ names). I want to have a really fast autocomplete function that shows results while people are typing the first few letters of the first & last name. I already have a solution that uses a regex, but it needs to iterate over all names which is to slow.
A very good data structure would be a Burst Trie
There's a Scala implementation.
You could try a second trie with the reversed string and a wildcard search:http://phpir.com/tries-and-wildcards/
I think that a sorted array will also fit for your requirements, an array containing Person objects (they have a firstName and a lastName field). Let's say that you have a prefix and want to find all the values that fit your prefix. Simply run a binary search to find the first position (let's say is firstIndex) where your prefix appears on firstName and one more to find the last position (lastIndex). Now you can retrieve your values in O(lastIndex - firstIndex). The same goes when you want to find them by lastName. When you have a prefixFirstName and a prefixLastName you can search for the interval where values match for prefixFirstName and then, on this interval, you can check for the values matching the prefixLastName. For a conclusion, when you have one or two prefixes you run 4 binary searches (around 17 iterations per search for 100k names) which is fast enough and you can retrieve them in linear time. Even if it isn't the fastest solution, I suggested it since it's easy to understand and easy to code.
I need a efficient data structure for searching. Currently I am using a simple List from System.Collections.Generic until I find a good solution.
The user can add/remove strings at runtime by clicking on them in a list. But the main operation is searching because every time the user want's to see the list I need to check for every entry if the user already clicked on it before. The list may contain about 100-1000 entries of which the user can choose about 100. The list with the chosen strings will also be saved as a string array to disk and needs to be loaded again. So the data structure should be fast to rebuild from a string array if the array was saved in the correct order.
I thought about using an AVL tree. Is it a good solution? Or would hashing be possible (I don't know the strings that can be chosen at compile time)?
Since you are using C# I would recommend using: Dictionary. It will allow you to store strings in a Hash Map (which is a related to Java's Map). The benefit of storing strings in a Dictionary is similar to that of a hash table which will allow constant time of searching, inserting, and deleting. Should you want to check if there are duplicate values you can check here for more information: Finding duplicate values in dictionary and print Key of the duplicate element.
Suppose you want to write a program that implements a simple phone book. Given a particular name, you want to be able to retrieve that person's phone number as quickly as possible. What data structure would you use to store the phone book, and why?
the text below answers your question.
In computer science, a hash table or hash map is a data structure that
uses a hash function to map identifying values, known as keys (e.g., a
person's name), to their associated values (e.g., their telephone
number). Thus, a hash table implements an associative array. The hash
function is used to transform the key into the index (the hash) of an
array element (the slot or bucket) where the corresponding value is to
be sought.
the text is from wiki:hashtable.
there are some further discussions, like collision, hash functions... check the wiki page for details.
I respect & love hashtables :) but even a balanced binary tree would be fine for your phone book application giving you in worst case a logarithmic complexity and avoiding you for having good hash functions, collisions etc. which is more suitable for huge amounts of data.
When I talk about huge data what I mean is something related to storage. Every time you fill all of the buckets in a hash-table you will need to allocate new storage and re-hash everything. This can be avoided if you know the size of the data ahead of time. Balanced trees wont let you go into these problems. Domain needs to be considered too while designing data structures, for an example for small devices storage matters a lot.
I was wondering why 'Tries' didn't come up in one of the answers,
Tries is suitable for Phone book kind of data.
Also, saving space compared to HashTable at the same cost(almost) of Retrieval efficiency, (assuming constant size alphabet & constant length Names)
Tries also facilitate the 'Prefix Matches' sometimes required while searching.
A dictionary is both dynamic and fast.
You want a dictionary, where you use the name as the key, and the number as the data stored. Check this out: http://en.wikipedia.org/wiki/Dictionary_%28data_structure%29
Why not use a singly linked list? Each node will have the name, number and link information.
One drawback is that your search might take some time since you'll have to traverse the entire list from link to link. You might order the list at the time of node insertion itself!
PS: To make the search a tad bit faster, maintain a link to the middle of the list. Search can continue to the left or right of the list based on the value of the "name" field at this node. Note that this requires a doubly linked list.
I am looking for the optimal (time and space) optimal data structure for supporting the following operations:
Add Persons (name, age) to a global data store of persons
Fetch Person with minimum and maximum age
Search for Person's age given the name
Here's what I could think of:
Keep an array of Persons, and keep adding to end of array when a new Person is to be added
Keep a hash of Person name vs. age, to assist in fetching person's age with given name
Maintain two objects minPerson and maxPerson for Person with min and max age. Update this if needed, when a new Person is added.
Now, although I keep a hash for better performance of (3), I think it may not be the best way if there are many collisions in the hash. Also, addition of a Person would mean an overhead of adding to the hash.
Is there anything that can be further optimized here?
Note: I am looking for the best (balanced) approach to support all these operations in minimum time and space.
You can get rid of the array as it doesn't provide anything that the other two structures can't do.
Otherwise, a hashtable + min/max is likely to perform well for your use case. In fact, this is precisely what I would use.
As to getting rid of the hashtable because a poor hash function might lead to collisions: well, don't use a poor hash function. I bet that the default hash function for strings that's provided by your programming language of choice is going to do pretty well out of the box.
It looks like that you need a data structure that needs fast inserts and that also supports fast queries on 2 different keys (name and age).
I would suggest keeping two data structures, one a sorted data structure (e.g. a balanced binary search tree) where the key is the age and the value is a pointer to the Person object, the other a hashtable where the key is the name and the value is a pointer to the Person object. Notice we don't keep two copies of the same object.
A balanced binary search tree would provide O(log(n)) inserts and max/min queries, while the hastable would give us O(1) (amortized) inserts and lookups.
When we add a new Person, we just add a pointer to it to both data structures. For a min/max age query, we can retrieve the Object by querying the BST. For a name query we can just query the hashtable.
Your question does not ask for updates/deletes, but those are also doable by suitably updating both data structures.
It sounds like you're expecting the name to be the unique idenitifer; otherwise your operation 3 is ambiguous (What is the correct return result if you have two entries for John Smith?)
Assuming that the uniqueness of a name is guaranteed, I would go with a plain hashtable keyed by names. Operation 1 and 3 are trivial to execute. Operation 2 could be done in O(N) time if you want to search through the data structure manually, or you can do like you suggest and keep track of the min/max and update it as you add/delete entries in the hash table.
What Data Structure could I use to find the Phone number of a person given the person's name?
Assuming you will only ever query using the person's name, the best option is to use an associative data structure. This is basically a data structure, usually implemented as a hashtable or a balanced binary search tree, that stores data as key=>value (or, stated in another way, as (key,value) pairs). You query the data structure by using the key and it returns the corresponding value. In your case, the key would be the name of the person and the value would be the phone number.
Rather than implementing a hashtable or a binary search tree for this yourself, check to see if your language has something like this already in its library, most languages these days do. Python has dict, perl has hashes, Java and C# has Map, and C++ has the STL map.
Things can get a little trickier if you have several values for the same key (e.g. the same person having multiple phone numbers), but there are workarounds like using a list/vector as the value, or using a slightly different structure that supports multiple values for the same key (e.g. STL multimap). But you probably don't need to worry about that anyway.
An associative array, such as a hashtable.
Really, anything that maps keys to values. The specific data structure will depend on the language you are using (unless you want to implement your own, in which case you have free reign).