📜  实施电话目录

📅  最后修改于: 2021-04-17 11:39:05             🧑  作者: Mango

给定电话目录中存在的联系人列表。任务是对电话目录实施搜索查询。字符串“ str ”上的搜索查询显示所有前缀为“ str ”的联系人。搜索函数的一个特殊属性是,当用户从联系人列表中搜索联系人时,在用户输入每个字符后会显示建议(带有前缀的联系人作为输入的字符串)。

注意:列表中的联系人仅包含小写字母。

例子:

Input : contacts [] = {“gforgeeks” , “geeksquiz” }
        Query String = “gekk”

Output : Suggestions based on "g" are 
         geeksquiz
         gforgeeks

         Suggestions based on "ge" are 
         geeksquiz

         No Results Found for "gek" 

         No Results Found for "gekk" 

使用Trie数据结构可以有效地实现电话目录。我们将所有联系人插入到Trie中。

通常,在Trie上的搜索查询是确定该字符串是否存在于Trie中,但是在这种情况下,要求我们查找所有前缀为’str’的所有字符串。这等效于在图形上进行DFS遍历。在Trie节点上,访问相邻的Trie节点,然后递归执行此操作,直到不再有相邻节点为止。这种递归函数需要2个参数作为一个字典树节点指向当前的字典树节点被访问和其他作为存储字符串迄今为止发现的前缀为“STR”的字符串。
每个Trie节点都存储一个布尔变量’isLast’,如果该节点表示contact(word)的末尾,则为true。

// This function displays all words with given
// prefix.  "node" represents last node when 
// path from root follows characters of "prefix".
displayContacts (TreiNode node, string prefix)
    If (node.isLast is true)
        display prefix

        // finding adjacent nodes
    for each character ‘i’ in lower case Alphabets 
        if (node.child[i] != NULL)
            displayContacts(node.child[i], prefix+i)

用户将进入由字符字符串的字符,我们需要每一个输入的字符后形成的词头显示建议。
因此,找到以形成的字符串开头的前缀的一种方法是检查Trie中是否存在该前缀,如果存在,则调用displayContacts()函数。通过这种方法,在每个输入的字符,我们检查字符串存在于Trie中。
无需一次又一次地检查,我们可以维护一个指针prevNode ‘,该指针指向用户最后输入的字符所对应的TrieNode,现在,当用户输入另一个字符进行检查时,我们需要检查子节点中的’prevNode’如果在Trie中存在。如果新前缀不在Trie中,那么在Trie中也找不到在’prefix’之后输入字符形成的所有字符串。因此,我们打破了用于一一生成前缀的循环,并为所有剩余字符打印“未找到结果”。

C++
// C++ Program to Implement a Phone
// Directory Using Trie Data Structure
#include 
using namespace std;
  
struct TrieNode
{
    // Each Trie Node contains a Map 'child'
    // where each alphabet points to a Trie
    // Node.
    // We can also use a fixed size array of
    // size 256.
    unordered_map child;
  
    // 'isLast' is true if the node represents
    // end of a contact
    bool isLast;
  
    // Default Constructor
    TrieNode()
    {
        // Initialize all the Trie nodes with NULL
        for (char i = 'a'; i <= 'z'; i++)
            child[i] = NULL;
  
        isLast = false;
    }
};
  
// Making root NULL for ease so that it doesn't
// have to be passed to all functions.
TrieNode *root = NULL;
  
// Insert a Contact into the Trie
void insert(string s)
{
    int len = s.length();
  
    // 'itr' is used to iterate the Trie Nodes
    TrieNode *itr = root;
    for (int i = 0; i < len; i++)
    {
        // Check if the s[i] is already present in
        // Trie
        TrieNode *nextNode = itr->child[s[i]];
        if (nextNode == NULL)
        {
            // If not found then create a new TrieNode
            nextNode = new TrieNode();
  
            // Insert into the Map
            itr->child[s[i]] = nextNode;
        }
  
        // Move the iterator('itr') ,to point to next
        // Trie Node
        itr = nextNode;
  
        // If its the last character of the string 's'
        // then mark 'isLast' as true
        if (i == len - 1)
            itr->isLast = true;
    }
}
  
// This function simply displays all dictionary words
// going through current node. String 'prefix'
// represents string corresponding to the path from
// root to curNode.
void displayContactsUtil(TrieNode *curNode, string prefix)
{
    // Check if the string 'prefix' ends at this Node
    // If yes then display the string found so far
    if (curNode->isLast)
        cout << prefix << endl;
  
    // Find all the adjacent Nodes to the current
    // Node and then call the function recursively
    // This is similar to performing DFS on a graph
    for (char i = 'a'; i <= 'z'; i++)
    {
        TrieNode *nextNode = curNode->child[i];
        if (nextNode != NULL)
            displayContactsUtil(nextNode, prefix + (char)i);
    }
}
  
// Display suggestions after every character enter by
// the user for a given query string 'str'
void displayContacts(string str)
{
    TrieNode *prevNode = root;
  
    string prefix = "";
    int len = str.length();
  
    // Display the contact List for string formed
    // after entering every character
    int i;
    for (i=0; ichild[lastChar];
  
        // If nothing found, then break the loop as
        // no more prefixes are going to be present.
        if (curNode == NULL)
        {
            cout << "nNo Results Found for "" << prefix
                 << "" n";
            i++;
            break;
        }
  
        // If present in trie then display all
        // the contacts with given prefix.
        cout << "nSuggestions based on "" << prefix
             << "" are n";
        displayContactsUtil(curNode, prefix);
  
        // Change prevNode for next prefix
        prevNode = curNode;
    }
  
    // Once search fails for a prefix, we print
    // "Not Results Found" for all remaining
    // characters of current query string "str".
    for (; i


Java
// Java Program to Implement a Phone
// Directory Using Trie Data Structure
import java.util.*;
  
class TrieNode
{
    // Each Trie Node contains a Map 'child'
    // where each alphabet points to a Trie
    // Node.
    HashMap child;
  
    // 'isLast' is true if the node represents
    // end of a contact
    boolean isLast;
  
    // Default Constructor
    public TrieNode()
    {
        child = new HashMap();
  
        // Initialize all the Trie nodes with NULL
        for (char i = 'a'; i <= 'z'; i++)
             child.put(i,null);
  
        isLast = false;
    }
}
  
class Trie
{
    TrieNode root;
  
    // Insert all the Contacts into the Trie
    public void insertIntoTrie(String contacts[])
    {
        root = new TrieNode();
        int n = contacts.length;
        for (int i = 0; i < n; i++)
        {
            insert(contacts[i]);
        }
    }
  
    // Insert a Contact into the Trie
    public void insert(String s)
    {
        int len = s.length();
  
        // 'itr' is used to iterate the Trie Nodes
        TrieNode itr = root;
        for (int i = 0; i < len; i++)
        {
            // Check if the s[i] is already present in
            // Trie
            TrieNode nextNode = itr.child.get(s.charAt(i));
            if (nextNode == null)
            {
                // If not found then create a new TrieNode
                nextNode = new TrieNode();
  
                // Insert into the HashMap
                itr.child.put(s.charAt(i),nextNode);
            }
  
            // Move the iterator('itr') ,to point to next
            // Trie Node
            itr = nextNode;
  
            // If its the last character of the string 's'
            // then mark 'isLast' as true
            if (i == len - 1)
                itr.isLast = true;
        }
    }
  
    // This function simply displays all dictionary words
    // going through current node.  String 'prefix'
    // represents string corresponding to the path from
    // root to curNode.
    public void displayContactsUtil(TrieNode curNode,
                                   String prefix)
    {
  
        // Check if the string 'prefix' ends at this Node
        // If yes then display the string found so far
        if (curNode.isLast)
            System.out.println(prefix);
  
        // Find all the adjacent Nodes to the current
        // Node and then call the function recursively
        // This is similar to performing DFS on a graph
        for (char i = 'a'; i <= 'z'; i++)
        {
            TrieNode nextNode = curNode.child.get(i);
            if (nextNode != null)
            {
                displayContactsUtil(nextNode, prefix + i);
            }
        }
    }
  
    // Display suggestions after every character enter by
    // the user for a given string 'str'
    void displayContacts(String str)
    {
        TrieNode prevNode = root;
  
        // 'flag' denotes whether the string entered
        // so far is present in the Contact List
  
        String prefix = "";
        int len = str.length();
  
        // Display the contact List for string formed
        // after entering every character
        int i;
        for (i = 0; i < len; i++)
        {
            // 'str' stores the string entered so far
            prefix += str.charAt(i);
  
            // Get the last character entered
            char lastChar = prefix.charAt(i);
  
            // Find the Node corresponding to the last
            // character of 'str' which is pointed by
            // prevNode of the Trie
            TrieNode curNode = prevNode.child.get(lastChar);
  
            // If nothing found, then break the loop as
            // no more prefixes are going to be present.
            if (curNode == null)
            {
                System.out.println("nNo Results Found for ""
                                          + prefix + """);
                i++;
                break;
            }
  
            // If present in trie then display all
            // the contacts with given prefix.
            System.out.println("nSuggestions based on ""
                                    + prefix + "" are");
            displayContactsUtil(curNode, prefix);
  
            // Change prevNode for next prefix
            prevNode = curNode;
        }
  
        for ( ; i < len; i++)
        {
            prefix += str.charAt(i);
            System.out.println("nNo Results Found for ""
                                          + prefix + """);
        }
    }
}
  
// Driver code
class Main
{
    public static void main(String args[])
    {
        Trie trie = new Trie();
  
        String contacts [] = {"gforgeeks", "geeksquiz"};
  
        trie.insertIntoTrie(contacts);
  
        String query = "gekk";
  
        // Note that the user will enter 'g' then 'e' so
        // first display all the strings with prefix as 'g'
        // and then all the strings with prefix as 'ge'
        trie.displayContacts(query);
    }
}


C#
// C# Program to Implement a Phone 
// Directory Using Trie Data Structure 
using System;
using System.Collections.Generic;
  
class TrieNode 
{ 
    // Each Trie Node contains a Map 'child' 
    // where each alphabet points to a Trie 
    // Node. 
    public Dictionary child; 
  
    // 'isLast' is true if the node represents 
    // end of a contact 
    public bool isLast; 
  
    // Default Constructor 
    public TrieNode() 
    { 
        child = new Dictionary(); 
  
        // Initialize all the Trie nodes with NULL 
        for (char i = 'a'; i <= 'z'; i++) 
            child.Add(i, null); 
  
        isLast = false; 
    } 
} 
  
class Trie 
{ 
    public TrieNode root; 
  
    // Insert all the Contacts into the Trie 
    public void insertIntoTrie(String []contacts) 
    { 
        root = new TrieNode(); 
        int n = contacts.Length; 
        for (int i = 0; i < n; i++) 
        { 
            insert(contacts[i]); 
        } 
    } 
  
    // Insert a Contact into the Trie 
    public void insert(String s) 
    { 
        int len = s.Length; 
  
        // 'itr' is used to iterate the Trie Nodes 
        TrieNode itr = root; 
        for (int i = 0; i < len; i++) 
        { 
            // Check if the s[i] is already present in 
            // Trie 
            TrieNode nextNode = itr.child[s[i]]; 
            if (nextNode == null) 
            { 
                // If not found then create a new TrieNode 
                nextNode = new TrieNode(); 
  
                // Insert into the Dictionary 
                if(itr.child.ContainsKey(s[i]))
                    itr.child[s[i]] = nextNode; 
                else
                    itr.child.Add(s[i], nextNode); 
            } 
  
            // Move the iterator('itr') ,to point to next 
            // Trie Node 
            itr = nextNode; 
  
            // If its the last character of the string 's' 
            // then mark 'isLast' as true 
            if (i == len - 1) 
                itr.isLast = true; 
        } 
    } 
  
    // This function simply displays all dictionary words 
    // going through current node. String 'prefix' 
    // represents string corresponding to the path from 
    // root to curNode. 
    public void displayContactsUtil(TrieNode curNode, 
                                    String prefix) 
    { 
  
        // Check if the string 'prefix' ends at this Node 
        // If yes then display the string found so far 
        if (curNode.isLast) 
            Console.WriteLine(prefix); 
  
        // Find all the adjacent Nodes to the current 
        // Node and then call the function recursively 
        // This is similar to performing DFS on a graph 
        for (char i = 'a'; i <= 'z'; i++) 
        { 
            TrieNode nextNode = curNode.child[i]; 
            if (nextNode != null) 
            { 
                displayContactsUtil(nextNode, prefix + i); 
            } 
        } 
    } 
  
    // Display suggestions after every character enter by 
    // the user for a given string 'str' 
    public void displayContacts(String str) 
    { 
        TrieNode prevNode = root; 
  
        // 'flag' denotes whether the string entered 
        // so far is present in the Contact List 
  
        String prefix = ""; 
        int len = str.Length; 
  
        // Display the contact List for string formed 
        // after entering every character 
        int i; 
        for (i = 0; i < len; i++) 
        { 
            // 'str' stores the string entered so far 
            prefix += str[i]; 
  
            // Get the last character entered 
            char lastChar = prefix[i]; 
  
            // Find the Node corresponding to the last 
            // character of 'str' which is pointed by 
            // prevNode of the Trie 
            TrieNode curNode = prevNode.child[lastChar]; 
  
            // If nothing found, then break the loop as 
            // no more prefixes are going to be present. 
            if (curNode == null) 
            { 
                Console.WriteLine("\nNo Results Found for'"
                                           + prefix + "'"); 
                i++; 
                break; 
            } 
  
            // If present in trie then display all 
            // the contacts with given prefix. 
            Console.WriteLine("Suggestions based on '"     
                                  + prefix + "' are"); 
            displayContactsUtil(curNode, prefix); 
  
            // Change prevNode for next prefix 
            prevNode = curNode; 
        } 
  
        for ( ; i < len; i++) 
        { 
            prefix += str[i]; 
            Console.WriteLine("\nNo Results Found for '"
                                        + prefix + "'"); 
        } 
    } 
} 
  
// Driver code 
public class GFG 
{ 
    public static void Main(String []args) 
    { 
        Trie trie = new Trie(); 
  
        String []contacts = {"gforgeeks", "geeksquiz"}; 
  
        trie.insertIntoTrie(contacts); 
  
        String query = "gekk"; 
  
        // Note that the user will enter 'g' then 'e' so 
        // first display all the strings with prefix as 'g' 
        // and then all the strings with prefix as 'ge' 
        trie.displayContacts(query); 
    } 
} 
  
// This code is contributed by PrinciRaj1992


输出:

Suggestions based on "g" are 
geeksquiz
gforgeeks

Suggestions based on "ge" are 
geeksquiz

No Results Found for "gek" 

No Results Found for "gekk"