Sorting array of strings (or words) using Trie | Set-2 (Handling Duplicates) - GeeksforGeeks

09 Jul, 2021
Given an array of strings, print them in alphabetical (dictionary) order. If there are duplicates in input array, we need to print all the occurrences.Examples:  
Input : arr[] = { "abc", "xyz", "abcd", "bcd", "abc" }
Output : abc abc abcd bcd xyz

Input : arr[] = { "geeks", "for", "geeks", "a", "portal", 
                  "to", "learn" }
Output : a for geeks geeks learn portal to
 
Prerequisite: Trie | (Insert and Search). Approach: In the previous post array of strings is being sorted, printing only single occurrence of duplicate strings. In this post all occurrences of duplicate strings are printed in lexicographic order. To print the strings in alphabetical order we have to first insert them in the trie and then perform preorder traversal to print in alphabetical order. The nodes of trie contain an index[] array which stores the index position of all the strings of arr[] ending at that node. Except for trie’s leaf node all the other nodes have size 0 for the index[] array.Below is the implementation of the above approach. 
C++
Java
C#
Python3
Javascript
// C++ implementation to sort an array// of strings using Trie#include <bits/stdc++.h>using namespace std; const int MAX_CHAR = 26; struct Trie {     // 'index' vectors size is greater than    // 0 when node/ is a leaf node, otherwise    // size is 0;    vector<int> index;     Trie* child[MAX_CHAR];     /*to make new trie*/    Trie()    {        // initializing fields        for (int i = 0; i < MAX_CHAR; i++)            child[i] = NULL;    }}; // function to insert a string in trievoid insert(Trie* root, string str, int index){    Trie* node = root;     for (int i = 0; i < str.size(); i++) {         // taking ascii value to find index of        // child node        char ind = str[i] - 'a';         // making a new path if not already        if (!node->child[ind])            node->child[ind] = new Trie();         // go to next node        node = node->child[ind];    }     // Mark leaf (end of string) and store    // index of 'str' in index[]    (node->index).push_back(index);} // function for preorder traversal of trievoid preorder(Trie* node, string arr[]){    // if node is empty    if (node == NULL)        return;     for (int i = 0; i < MAX_CHAR; i++) {        if (node->child[i] != NULL) {             // if leaf node then print all the strings            // for (node->child[i]->index).size() > 0)            for (int j = 0; j < (node->child[i]->index).size(); j++)                cout << arr[node->child[i]->index[j]] << " ";             preorder(node->child[i], arr);        }    }} // function to sort an array// of strings using Trievoid printSorted(string arr[], int n){    Trie* root = new Trie();     // insert all strings of dictionary into trie    for (int i = 0; i < n; i++)        insert(root, arr[i], i);     // print strings in lexicographic order    preorder(root, arr);} // Driver program to test aboveint main(){    string arr[] = { "abc", "xyz", "abcd", "bcd", "abc" };    int n = sizeof(arr) / sizeof(arr[0]);    printSorted(arr, n);    return 0;}
// Java implementation// to sort an array of// strings using Trieimport java.util.*; class Trie {     private Node rootNode;     /*to make new trie*/    Trie()    {        rootNode = null;    }     // function to insert    // a string in trie    void insert(String key, int index)    {        // making a new path        // if not already        if (rootNode == null)        {            rootNode = new Node();        }         Node currentNode = rootNode;         for (int i = 0;i < key.length();i++)        {            char keyChar = key.charAt(i);                 if (currentNode.getChild(keyChar) == null)            {                currentNode.addChild(keyChar);            }                         // go to next node            currentNode = currentNode.getChild(keyChar);        }         // Mark leaf (end of string)        // and store index of 'str'        // in index[]        currentNode.addIndex(index);    }     void traversePreorder(String[] array)    {        traversePreorder(rootNode, array);    }     // function for preorder    // traversal of trie    private void traversePreorder(Node node,                             String[] array)    {        if (node == null)        {            return;        }         if (node.getIndices().size() > 0)        {            for (int index : node.getIndices())            {                System.out.print(array[index] + " ");            }        }         for (char index = 'a';index <= 'z';index++)        {            traversePreorder(node.getChild(index), array);        }    }     private static class Node {         private Node[] children;        private List<Integer> indices;         Node()        {            children = new Node[26];            indices = new ArrayList<>(0);        }         Node getChild(char index)        {            if (index < 'a' || index > 'z')            {                return null;            }                         return children[index - 'a'];        }         void addChild(char index)        {            if (index < 'a' || index > 'z')            {                return;            }                         Node node = new Node();            children[index - 'a'] = node;        }         List<Integer> getIndices()        {            return indices;        }         void addIndex(int index)        {            indices.add(index);        }    }} class SortStrings {     // Driver program    public static void main(String[] args)    {        String[] array = { "abc", "xyz",                    "abcd", "bcd", "abc" };        printInSortedOrder(array);    }     // function to sort an array    // of strings using Trie    private static void printInSortedOrder(String[] array)    {        Trie trie = new Trie();                 for (int i = 0;i < array.length;i++)        {            trie.insert(array[i], i);        }                 trie.traversePreorder(array);    }} // Contributed by Harikrishnan Rajan
// C# implementation// to sort an array of// strings using Trieusing System;using System.Collections.Generic; public class Trie{     public Node rootNode;     /* to make new trie*/    public Trie()    {        rootNode = null;    }     // function to insert    // a string in trie    public void insert(String key, int index)    {        // making a new path        // if not already        if (rootNode == null)        {            rootNode = new Node();        }         Node currentNode = rootNode;         for (int i = 0;i < key.Length;i++)        {            char keyChar = key[i];                 if (currentNode.getChild(keyChar) == null)            {                currentNode.addChild(keyChar);            }                         // go to next node            currentNode = currentNode.getChild(keyChar);        }         // Mark leaf (end of string)        // and store index of 'str'        // in index[]        currentNode.addIndex(index);    }     public void traversePreorder(String[] array)    {        traversePreorder(rootNode, array);    }     // function for preorder    // traversal of trie    public void traversePreorder(Node node,                            String[] array)    {        if (node == null)        {            return;        }         if (node.getIndices().Count > 0)        {            foreach (int index in node.getIndices())            {                Console.Write(array[index] + " ");            }        }         for (char index = 'a';index <= 'z';index++)        {            traversePreorder(node.getChild(index), array);        }    }     public class Node    {         public Node[] children;        public List<int> indices;         public Node()        {            children = new Node[26];            indices = new List<int>(0);        }         public Node getChild(char index)        {            if (index < 'a' || index > 'z')            {                return null;            }                         return children[index - 'a'];        }         public void addChild(char index)        {            if (index < 'a' || index > 'z')            {                return;            }                         Node node = new Node();            children[index - 'a'] = node;        }         public List<int> getIndices()        {            return indices;        }         public void addIndex(int index)        {            indices.Add(index);        }    }} public class SortStrings{     // Driver code    public static void Main(String[] args)    {        String[] array = { "abc", "xyz",                    "abcd", "bcd", "abc" };        printInSortedOrder(array);    }     // function to sort an array    // of strings using Trie    static void printInSortedOrder(String[] array)    {        Trie trie = new Trie();                 for (int i = 0;i < array.Length;i++)        {            trie.insert(array[i], i);        }                 trie.traversePreorder(array);    }} // This code has been contributed by 29AjayKumar
# Python implementation to sort an array# of strings using Triefrom typing import ListMAX_CHAR = 26class Trie:    def __init__(self) -> None:         # 'index' vectors size is greater than        # 0 when node/ is a leaf node, otherwise        # size is 0;        self.index = []        self.child = [None for _ in range(MAX_CHAR)] # function to insert a string in triedef insert(root: Trie, string: str, index: int) -> None:    node = root    for i in range(len(string)):         # taking ascii value to find index of        # child node        ind = ord(string[i]) - ord('a')         # making a new path if not already        if (node.child[ind] == None):            node.child[ind] = Trie()         # go to next node        node = node.child[ind]     # Mark leaf (end of string) and store    # index of 'str' in index[]    (node.index).append(index) # function for preorder traversal of triedef preorder(node: Trie, arr: List[str]) -> None:     # if node is empty    if (node == None):        return    for i in range(MAX_CHAR):        if (node.child[i] != None):             # if leaf node then print all the strings            # for (node.child[i].index).size() > 0)            for j in range(len(node.child[i].index)):                print(arr[node.child[i].index[j]], end = " ")            preorder(node.child[i], arr) # function to sort an array# of strings using Triedef printSorted(arr: List[str], n: int) -> None:    root = Trie()     # insert all strings of dictionary into trie    for i in range(n):        insert(root, arr[i], i)     # print strings in lexicographic order    preorder(root, arr) # Driver program to test aboveif __name__ == "__main__":     arr = ["abc", "xyz", "abcd", "bcd", "abc"]    n = len(arr)    printSorted(arr, n) # This code is contributed by sanjeev2552
<script> // JavaScript implementation// to sort an array of// strings using Trie let rootNode=null;  // function to insert    // a string in triefunction insert(key,index){    // making a new path        // if not already        if (rootNode == null)        {            rootNode = new Node();        }          let currentNode = rootNode;          for (let i = 0;i < key.length;i++)        {            let keyChar = key[i];                  if (currentNode.getChild(keyChar) == null)            {                currentNode.addChild(keyChar);            }                          // go to next node            currentNode = currentNode.getChild(keyChar);        }          // Mark leaf (end of string)        // and store index of 'str'        // in index[]        currentNode.addIndex(index);} // function for preorder    // traversal of triefunction traversePreorder(array){    _traversePreorder(rootNode, array);} function _traversePreorder(node,array){    if (node == null)        {            return;        }          if (node.getIndices().length > 0)        {            for (let index=0;index<            node.getIndices().length;index++)            {                document.write(array[node.getIndices()[index]] + " ");            }        }          for (let index = 'a'.charCodeAt(0);index <=        'z'.charCodeAt(0);index++)        {           _traversePreorder(node.getChild(String.fromCharCode(index)),           array);        }} class Node{    constructor()    {        this.children = new Array(26);        this.indices = [];    }         getChild(index)    {        if (index < 'a' || index > 'z')            {                return null;            }                          return this.children[index.charCodeAt(0) -            'a'.charCodeAt(0)];    }         addChild(index)    {        if (index < 'a' || index > 'z')            {                return;            }                          let node = new Node();            this.children[index.charCodeAt(0) -            'a'.charCodeAt(0)] = node;    }         getIndices()    {        return this.indices;    }         addIndex(index)    {        this.indices.push(index);    }     } // function to sort an array    // of strings using Triefunction printInSortedOrder(array){                       for (let i = 0;i < array.length;i++)        {            insert(array[i], i);        }                  traversePreorder(array);}  // Driver programarray=["abc", "xyz","abcd", "bcd", "abc"]; printInSortedOrder(array); // This code is contributed by rag2127 </script>
Output:  
abc abc abcd bcd xyz
Time Complexity: Worst case occurs when every string is starting with a different character. In that case, it will visit all the nodes of each character of each string. So worst-case time complexity will be the sum of the length of every string i.e. O(|S1| + |S2| + |S3| + ... + |Sn|) where |S| is the length of the string. 
29AjayKumar
Aakash_Panchal
sanjeev2552
rag2127
Trie
Advanced Data Structure
Sorting
Sorting
Trie
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Ordered Set and GNU C++ PBDS
2-3 Trees | (Search, Insert and Deletion)
Extendible Hashing (Dynamic approach to DBMS)
Suffix Array | Set 1 (Introduction)
Difference between Backtracking and Branch-N-Bound technique