【问题标题】:How to implement remove method in Trie data structure?如何在 Trie 数据结构中实现 remove 方法?
【发布时间】:2014-04-02 17:55:41
【问题描述】:

我正在尝试实现PatriciaTrie 数据结构。我最近在通过 Google Docs 进行的编码面试中被问到这个问题。但我无法回答这个问题。

我通过在下面的代码中添加 insert 方法取得了一些进展,但在 PatriciaTrie 代码中的 remove 方法上卡住了 - 不知道如何实现它 -

下面是我的PatriciaTrie 代码-

public class PatriciaTrie {

    protected static class Edge {
        Node target;
        TTString label;
        public Edge(Node target, TTString label) {
            this.target = target;
            this.label = label;
        }
    }

    protected static class Node {
        Edge[] edges;           // the children of this node
        int numberOfChildren;   // the number of children
        public Node() {
            edges = new Edge[128];
            numberOfChildren = 0;
        }
    }

    /**
     * number of strings stored in the trie
     */
    protected int number;

    /**
     * This is root
     */
    protected Node root;

    public PatriciaTrie() {
        root = new Node();
        number = 0;
    }

    /** 
     * Add the x to this trie
     * @param x the string to add
     * @return true if x was successfully added or false if x is already in the trie
     */
    public boolean insert(TTString x) {
        Node current = root;
        for (int i = 0; i < x.length(); i++) {
            TTString ch = x.subString(i, 1);
            if (current.edges[x.charAt(i)] != null) {
                Node child = current.edges[x.charAt(i)].target;
                current = child;
            } else {
                current.edges[x.charAt(i)] = new Edge(new Node(), ch);
                current.numberOfChildren++;
                current = current.edges[x.charAt(i)].target;
            }
            if (i == x.length() - 1)
                return true;
        }
        return false;
    }

    /** 
     * Remove x from this trie
     * @param x the string to remove
     * @return true if x was successfully removed or false if x is not stored in the trie
     */
    public boolean remove(TTString x) {
        // not sure how to do this

        return false;
    }       
}

下面是我的TTString类-

public class TTString {
    int i;        // index of first character  
    int m;        // length
    byte[] data;  // data 

    public TTString(String s) {
        data = s.getBytes();
        i = 0;
        m = s.length();
    }

    protected TTString(byte[] data, int i, int m) {
        this.data = data;
        this.i = i;
        this.m = m;
    }

    public TTString subString(int j, int n) {
        if (j < 0 || j >= m) throw new IndexOutOfBoundsException();
        if (n < 0 || j + n > m) throw new IndexOutOfBoundsException();
        return new TTString(data, i+j, n);
    }

    /**
     * The length of this string
     * @return
     */
    public int length() {
        return m;
    }

    /**
     * Return the character at index j
     * @param j
     * @return
     */
    public char charAt(int j) {
        return (char)data[i+j];
    }
}

关于如何在这里实现remove 方法有什么想法吗?

【问题讨论】:

    标签: java algorithm data-structures trie


    【解决方案1】:

    一个思路是:从根到x的最后一个字符对应的叶子(假设有包含x的路径,否则没有什么可改变的),在过程中记住你的路径上的最后一个fork(第一个叉子在根)。当您在叶子上时,从最后一个叉子到叶子删除所有边/节点。

    【讨论】:

      【解决方案2】:

      我已经用 C# 在 TRIE 数据结构上实现了它,字符串代码如下。你可以在这里看到完整的代码http://devesh4blog.wordpress.com/2013/11/16/real-time-auto-complete-using-trie-in-c/

             public void RemoveWord(string word, TRIENode rootNode, string id)
          {
              int len = word.Length;
              if (len == 0)
              {
                  rootNode.PrefixCount--;
                  if (rootNode.PrefixCount == 0)
                      rootNode.IsCompleteWord = false;
                  rootNode.Ids.Remove(id);
                  return;
              }
              for (int i = 0; i < len; i++)
              {
                  string key = word.Substring(i, 1);
                  string lowerVersionKey = key.ToLower();
                  rootNode.PrefixCount--;
                  rootNode = rootNode.Children[lowerVersionKey];
              }
              rootNode.Ids.Remove(id);
              if (rootNode.Ids.Count == 0)
                  rootNode.IsCompleteWord = false;
          }
      

      【讨论】:

        【解决方案3】:

        这是我的代码和示例测试:

        protected static class Edge {
            Node target;
            TTString label;
        
            public Edge(Node target, TTString label) {
                this.target = target;
                this.label = label;
            }
        }
        
        protected static class Node {
            Edge[] edges; // the children of this node
            int numberOfChildren; // the number of children
            // isEnd is true means this node is a string's end node.
            boolean isEnd;
        
            public Node() {
                edges = new Edge[128];
                numberOfChildren = 0;
                isEnd = false;
            }
        }
        
        /**
         * number of strings stored in the trie
         */
        protected int number;
        
        /**
         * This is root
         */
        protected Node root;
        
        public PatriciaTrie() {
            root = new Node();
            number = 0;
        }
        
        /**
         * Add the x to this trie
         * 
         * @param x
         *            the string to add
         * @return true if x was successfully added or false if x is already in the
         *         trie
         */
        public boolean insert(TTString x) {
            // not sure what I am supposed to do here?
            Node current = root;
            for (int i = 0; i < x.length(); i++) {
                TTString ch = x.subString(i, 1);
                if (current.edges[x.charAt(i)] != null) {
                    Node child = current.edges[x.charAt(i)].target;
                    current = child;
                } else {
                    current.edges[x.charAt(i)] = new Edge(new Node(), ch);
                    current.numberOfChildren++;
                    current = current.edges[x.charAt(i)].target;
                }
                if (i == x.length() - 1) {
                    // mark this node is the string x's end node.
                    current.isEnd = true;
                    return true;
                }
            }
            return false;
        }
        
        // find the string x in the trie, if true, return the x.
        public TTString find(TTString x) {
            boolean isOk = false;
            Node current = root;
            for (int i = 0; i < x.length(); i++) {
                if (current.edges[x.charAt(i)] != null) {
                    current = current.edges[x.charAt(i)].target;
                } else {
                    isOk = false;
                }
                if (i == x.length() - 1 && current.isEnd == true) {
                    isOk = true;
                }
            }
            if (isOk == false)
                return null;
            else
                return x;
        }
        
        public boolean remove(TTString x) {
            Node current = root;
            for (int i = 0; i < x.length(); i++) {
                if (current.edges[x.charAt(i)] != null) {
                    current = current.edges[x.charAt(i)].target;
                } else {
                    return false;
                }
                if (i == x.length() - 1) {
                    // delete the string x.
                    current.isEnd = false;
                    return true;
                }
            }
            return false;
        }
        
        void run() {
            /*
             * Here is the sample patricialTrie whose edges are labeled with
             * letters.
             */
            TTString tmp = new TTString("ABCD");
            System.out.println(insert(tmp) ? "YES" : "NO");
            Node current = root;
            for (int i = 0; i < tmp.length(); i++) {
                System.out.println(current.edges[tmp.charAt(i)].label.charAt(0));
                current = current.edges[tmp.charAt(i)].target;
            }
            tmp = new TTString("ABCDE");
            insert(tmp);
            tmp = new TTString("ABDF");
            insert(tmp);
        
            /*
             * remove method
             */
            tmp = new TTString("ABCDE");
            System.out.println(remove(tmp) ? "YES" : "NO");
            System.out.println(find(tmp) == null ? "NULL" : find(tmp));
            tmp = new TTString("ABCD");
            System.out.println(find(tmp) == null ? "NULL" : find(tmp));
        }
        
        public static void main(String args[]) {
            new PatriciaTrie().run();
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-30
          • 2020-03-09
          • 1970-01-01
          • 2016-03-16
          • 2013-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多