我正在尝试实现PatriciaTrie
数据结构。最近我通过Google Docs在编码访谈中问过这个问题。但我无法回答这个问题。
我通过在下面的代码中添加insert
方法取得了一些进展,但却陷入了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
方法的任何想法?
答案 0 :(得分:1)
一个想法是:从根到叶子对应于x
的最后一个字符(假设有包含x
的路径,否则没有什么可改变的),记住最后一个在进程中分叉你的路径(第一个分叉在根目录)。当您在叶子上时,从最后一个叉子中移除所有边缘/节点直到叶子。
答案 1 :(得分:0)
我已经在TRIE数据结构的C#中实现了它,字符串代码如下。您可以在此处查看完整代码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;
}
答案 2 :(得分:0)
这是我的代码和示例测试:
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();
}