Trie implementation in AS3
In this post, we will implement the Trie data structure in ActionScript 3. Then we will draw it to get a nice picture of this data structure.
What Trie is
Let’s say, our program gets a thousand words, which we have to store into some data structure. After, we will recieve requests, whether some word is contained in this set. If we store these words in linear array, it will be very unefficient (large memory and long running time when searching for a word). The model of Trie is more efficient. Read more on Wikipedia page.Class TNode
Whad do I want
I want an ability to easily create a Trie (var trie = new …), easily add words (trie.AddWord(“ahoj”);). Easily detect, whether my trie contains some word (if(trie.Contains(“hello”)) …).How to store children in trie node
Each node can have multiple children, their count is from 0 up to length of an alphabet. Alphabets are often very long (26 – small letters, 256 – ASCII characters, $2^{16}, 2^{24}, 2^{32}$ – Unicode characters). But nodes mostly don’t have all the children from an alphabet. I decided to have a fixed-length array and to hash pointers into it. In the example below, I have an array of 4 pointers, I store the pointer on [char code] mod 4. When collision happens, I put pointers into a linked list.
Basic class
package
{
public class TNode
{
// the array of 4 children of this node
public var cn:Vector.<TNode> = new Vector.<TNode>(4, true);
public var c:String; // character stored in the node
public var next:TNode; // pointer to the next node (in linked list)
public var isEnd:Boolean = false; // whether there is the end of word
public function TNode(c:String):void
{
this.c = c; // assign the parameter to "c"
}
}
}
Searching a child for a character
Since children are in fixed-length array + in linked lists, it is not so easy to get them, so we write this method:public function GetChild(s:String):TNode
{
// at first, take a look at the array "cn"
var n:TNode = cn[ s.charCodeAt(0)% 4 ];
if ( n == null) return null; // there is no child for "s"
else // there is some child, we loop through the linked list
while (n.next != null)
{
if (n.c == s) return n;
n = n.next;
}
if (n.c == s) return n; // it was at the end of LL
return null; // it wasn't anywhere
}
Adding a word into a Trie
At first, we read the first character of the word. If there already is a child for this charater, we add the rest of the word to this child. If not, we create a new node and add the rest of the word into it.public function AddWord(s:String):void
{
// look for child for this char
var n:TNode = GetChild(s.charAt(0));
if(n==null) // there is no child
{
n = new TNode(s.charAt(0)); // we chreate one
var pos:int = s.charCodeAt(0)% 4; // where should it be
if(cn[pos] == null) cn[pos] = n; // free position
else // not free - add it to LL
{
var no:TNode = cn[ pos ];
while(no.next != null) no = no.next;
no.next = n;
}
}
// add the rest of the word to it or set the flag
if(s.length>1) n.AddWord(s.substring(1,s.length));
else n.isEnd = true; // end of the word
}
Does Trie contain the word
public function Contains(s:String):Boolean
{
// at the end of recursion we return isEnd
if(s.length == 0) return isEnd;
// we look at the proper child
var n:TNode = GetChild(s.charAt(0));
if(n==null) return false; // no such child
else return n.Contains(s.substring(1,s.length)); // ask the child
}
Drawing a trie
We draw a Trie using very common code as when I was drawing Binary search tree.function drawTrie(n:TNode, x:int, y:int, w:int, place:Sprite)
{
var i:int;
// at first, we add chilren to array
var nodes:Array = new Array();
for(i = 0; i<4; i++)
{
var no:TNode = n.cn[i]; if(no == null) continue;
while(no != null){ nodes.push(no); no = no.next;}
}
var sW:int = w/nodes.length; // width for each node
for (i = 0; i < nodes.length; i++)
{
with(place.graphics) // line to child
{
lineStyle(3,0x00E1FF);
moveTo(x, y);
lineTo(x-w/2 + i*sW + sW/2, y+60);
}
// drawing a child
drawTrie(nodes[i], x-w/2 + i*sW + sW/2, y+60, sW, place);
}
// draw a round for this node
with(place.graphics)
{
if(n.isEnd) lineStyle(4, 0x000000); // když je koncový
else lineStyle(2, 0x333333); // když není - tenčí okraj
beginFill(0x6D00D9);
drawEllipse(x-14, y-14, 28, 28);
endFill();
}
// add text field with character
var tf:TextField = new TextField();
tf.text = n.c; tf.x = x-tf.textWidth; tf.y = y-14;
place.addChild(tf);
}
Thanks for such nice visual presentation. It helps me a lot to understand, and implement a trie.
July 4th, 2011..wow
May 7th, 2012where’s the download link?
May 7th, 2012kelangan ko nyan
May 7th, 2012Juan: How can I help you? You can download SWF and use it locally. You can copy the code and use it. If you made a donation, I can give you other things, what exactly do you need?
May 7th, 2012Hi this is too good….
August 22nd, 2012Could u pls give me the confirmation that will i b able to implement the same AC algorithm in verilog code……… pls do reply m waiting..
why does the constructor requires a string value ?
May 3rd, 2013Luis: It is because ActionScript does not have a character type, so I decided to work with one letter strings.
May 3rd, 2013