簡體   English   中英

如何在Trie數據結構中實現刪除方法?

[英]How to implement remove method in Trie data structure?

我正在嘗試實現PatriciaTrie數據結構。 最近在通過Google文檔進行的一次編程采訪中有人問我這個問題。 但是我無法回答這個問題。

我通過在下面的代碼中添加insert方法取得了一些進展,但是在PatriciaTrie代碼中的remove方法上遇到了PatriciaTrie -不知道如何實現-

以下是我的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方法有什么想法?

一個想法是:從根降到與x的最后一個字符相對應的葉子(假設存在包含x路徑,否則沒有任何更改),記住進程中路徑上的最后一個派生(第一個派生在根上) 。 當您在葉子上時,從最后一個叉子移除所有邊緣/節點直到葉子。

我已經在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;
    }

這是我的代碼和示例測試:

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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM