青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 42  文章 - 3  trackbacks - 0
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用鏈接

留言簿(2)

隨筆檔案

文章檔案

網頁收藏

搜索

  •  

最新評論

閱讀排行榜

評論排行榜


The original post is
http://igoro.com/archive/efficient-auto-complete-with-a-ternary-search-tree/

Over the past couple of years, auto-complete has popped up all over the web. Facebook, YouTube, Google, Bing, MSDN, LinkedIn and lots of other websites all try to complete your phrase as soon as you start typing.

Auto-complete definitely makes for a nice user experience, but it can be a challenge to implement efficiently. In many cases, an efficient implementation requires the use of interesting algorithms and data structures. In this blog post, I will describe one simple data structure that can be used to implement auto-complete: a ternary search tree.

Trie: simple but space-inefficient

Before discussing ternary search trees, let’s take a look at a simple data structure that supports a fast auto-complete lookup but needs too much memory: a trie. A trie is a tree-like data structure in which each node contains an array of pointers, one pointer for each character in the alphabet. Starting at the root node, we can trace a word by following pointers corresponding to the letters in the target word.

Each node could be implemented like this in C#:

class TrieNode
{
public const int ALPHABET_SIZE = 26;
public TrieNode[] m_pointers = new TrieNode[ALPHABET_SIZE];
public bool m_endsString = false;
}

Here is a trie that stores words AB, ABBA, ABCD, and BCD. Nodes that terminate words are marked yellow:

 

gif_1

 

Implementing auto complete using a trie is easy. We simply trace pointers to get to a node that represents the string the user entered. By exploring the trie from that node down, we can enumerate all strings that complete user’s input.

But, a trie has a major problem that you can see in the diagram above. The diagram only fits on the page because the trie only supports four letters {A,B,C,D}. If we needed to support all 26 English letters, each node would have to store 26 pointers. And, if we need to support international characters, punctuation, or distinguish between lowercase and uppercase characters, the memory usage grows becomes untenable.

Our problem has to do with the memory taken up by all the null pointers stored in the node arrays. We could consider using a different data structure in each node, such as a hash map. However, managing thousands and thousands of hash maps is generally not a good idea, so let’s take a look at a better solution.

Ternary search tree to the rescue

A ternary tree is a data structure that solves the memory problem of tries in a more clever way. To avoid the memory occupied by unnecessary pointers, each trie node is represented as a tree-within-a-tree rather than as an array. Each non-null pointer in the trie node gets its own node in a ternary search tree.

For example, the trie from the example above would be represented in the following way as a ternary search tree:

image

The ternary search tree contains three types of arrows. First, there are arrows that correspond to arrows in the corresponding trie, shown as dashed down-arrows. Traversing a down-arrow corresponds to “matching” the character from which the arrow starts. The left- and right- arrow are traversed when the current character does not match the desired character at the current position. We take the left-arrow if the character we are looking for is alphabetically before the character in the current node, and the right-arrow in the opposite case.

For example, green arrows show how we’d confirm that the ternary tree contains string ABBA:

 image

And this is how we’d find that the ternary string does not contain string ABD:

image 

Ternary search tree on a server

On the web, a significant chunk of the auto-complete work has to be done by the server. Often, the set of possible completions is large, so it is usually not a good idea to download all of it to the client. Instead, the ternary tree is stored on the server, and the client will send prefix queries to the server.

The client will send a query for words starting with “bin” to the server:

  image

And the server responds with a list of possible words:

image 

Implementation

Here is a simple ternary search tree implementation in C#:

public class TernaryTree
{
private Node m_root = null;
private void Add(string s, int pos, ref Node node)
{
if (node == null) { node = new Node(s[pos], false); }
if (s[pos] < node.m_char) { Add(s, pos, ref node.m_left); }
else if (s[pos] > node.m_char) { Add(s, pos, ref node.m_right); }
else
{
if (pos + 1 == s.Length) { node.m_wordEnd = true; }
else { Add(s, pos + 1, ref node.m_center); }
}
}
public void Add(string s)
{
if (s == null || s == "") throw new ArgumentException();
Add(s, 0, ref m_root);
}
public bool Contains(string s)
{
if (s == null || s == "") throw new ArgumentException();
int pos = 0;
Node node = m_root;
while (node != null)
{
int cmp = s[pos] - node.m_char;
if (s[pos] < node.m_char) { node = node.m_left; }
else if (s[pos] > node.m_char) { node = node.m_right; }
else
{
if (++pos == s.Length) return node.m_wordEnd;
node = node.m_center;
}
}
return false;
}
}

And here is the Node class:

class Node
{
internal char m_char;
internal Node m_left, m_center, m_right;
internal bool m_wordEnd;
public Node(char ch, bool wordEnd)
{
m_char = ch;
m_wordEnd = wordEnd;
}
}

Remarks

For best performance, strings should be inserted into the ternary tree in a random order. In particular, do not insert strings in the alphabetical order. Each mini-tree that corresponds to a single trie node would degenerate into a linked list, significantly increasing the cost of lookups. Of course, more complex self-balancing ternary trees can be implemented as well.

And, don’t use a fancier data structure than you have to. If you only have a relatively small set of candidate words (say on the order of hundreds) a brute-force search should be fast enough.

Further reading

Another article on tries is available on DDJ (careful, their implementation assumes that no word is a prefix of another):

http://www.ddj.com/windows/184410528

If you like this article, also check out these posts on my blog:


posted on 2012-06-25 23:26 鷹擊長空 閱讀(484) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品最新地址| 免播放器亚洲一区| 性欧美大战久久久久久久久| 99视频热这里只有精品免费| 欧美精品国产精品日韩精品| 亚洲人成人一区二区三区| 欧美亚洲一级| 欧美一区二区三区在线看| 亚洲欧美日韩天堂| 久久精品国产欧美激情| 久久久久久久网| 欧美va日韩va| 欧美黑人国产人伦爽爽爽| 亚洲另类自拍| 午夜免费日韩视频| 美女黄毛**国产精品啪啪| 欧美成人精品一区| 国产精品久久久久91| 国产婷婷成人久久av免费高清| 国产色综合天天综合网| 亚洲福利国产| 国产精品99久久不卡二区| 欧美一区二区三区免费看 | 快she精品国产999| 欧美极品色图| 国产精品日韩在线| 欧美一区二区三区日韩| 欧美日韩综合在线免费观看| 国产一区二区三区网站| 亚洲视频 欧洲视频| 久久久精品日韩欧美| 亚洲国产成人精品久久| 亚洲一区免费观看| 卡一卡二国产精品| 国产精品美女久久久久久久| 国产欧美精品一区二区三区介绍| 黑人中文字幕一区二区三区| 亚洲激情影院| 久久精品一区二区三区四区| 亚洲精品免费电影| 久久精品电影| 欧美日韩日本国产亚洲在线 | 欧美欧美在线| 亚洲国产cao| 欧美亚洲日本一区| 亚洲人体一区| 久久这里有精品15一区二区三区| 国产伦理一区| 亚洲欧美日本另类| 亚洲人屁股眼子交8| 亚洲免费观看| 欧美高清免费| 亚洲第一精品久久忘忧草社区| 欧美一级日韩一级| aa国产精品| 欧美国产日产韩国视频| 欧美亚洲一级| 国产精品影音先锋| 亚洲天堂激情| 一个人看的www久久| 欧美精品尤物在线| 日韩午夜剧场| 亚洲激情视频网| 另类欧美日韩国产在线| 国语精品中文字幕| 欧美一区二区视频观看视频| 最近中文字幕mv在线一区二区三区四区| 久久激情五月丁香伊人| 国产精品美女久久久久aⅴ国产馆| 亚洲视频在线观看网站| 亚洲国产高清aⅴ视频| 欧美高清在线视频| 在线一区二区三区四区| aa级大片欧美三级| 国产欧美日韩一区二区三区| 久久婷婷国产综合国色天香| 久久亚洲电影| 欧美日韩综合另类| 小黄鸭视频精品导航| 欧美亚洲尤物久久| 亚洲激情六月丁香| 一区二区三区欧美日韩| 国产亚洲一区精品| 欧美国产视频日韩| 国产精品久久久久久久久久免费| 欧美一区二区在线免费播放| 久久久一区二区三区| 99精品99| 欧美一区亚洲一区| 91久久精品日日躁夜夜躁欧美| 日韩视频中文字幕| 国产日本精品| 亚洲精品久久久久久久久久久| 欧美三级乱码| 欧美成人福利视频| 国产精品麻豆成人av电影艾秋| 久久综合网hezyo| 欧美日韩午夜精品| 久久性色av| 欧美日韩一区在线播放| 看片网站欧美日韩| 国产精品国产成人国产三级| 久久在线精品| 欧美日韩三区四区| 麻豆精品精品国产自在97香蕉| 欧美精品一区二区三区视频| 激情五月***国产精品| 欧美激情一区二区三区四区| 久久精品最新地址| 午夜一级久久| 91久久精品美女高潮| 国产精品夜色7777狼人| 亚洲女同性videos| 欧美日韩另类丝袜其他| 欧美精品一区二区三| 欧美电影在线免费观看网站| 国产精品美女午夜av| 午夜精品美女自拍福到在线| 欧美另类一区二区三区| 亚洲精品护士| 免播放器亚洲| 99视频在线精品国自产拍免费观看 | 亚洲在线免费视频| 久久三级福利| 久久精品国产成人| 久久av资源网站| 久久久福利视频| 狠狠做深爱婷婷久久综合一区 | 欧美日韩国产另类不卡| 免费久久99精品国产自| 久热国产精品视频| 久久影音先锋| 欧美成人日本| 欧美激情精品久久久久久蜜臀| 免费精品99久久国产综合精品| 国产一区91| 久久精品国产清自在天天线| 在线欧美影院| 欧美国产日韩一二三区| 亚洲一二三四久久| 欧美日韩国产二区| 欧美一区二区三区四区在线观看 | 午夜欧美精品久久久久久久| 亚洲国产精品久久精品怡红院| 久久精品在线播放| 亚洲一二三区精品| 欧美性猛交一区二区三区精品| 欧美中日韩免费视频| 久久久夜夜夜| 欧美激情导航| 国产精品欧美日韩| 欧美一区二区女人| 国产丝袜一区二区| 久久久精品免费视频| 亚洲精品久久久蜜桃| 欧美日韩在线播放一区二区| 美女精品国产| 日韩天天综合| 久久久精品tv| 欧美国产国产综合| 妖精视频成人观看www| 国产在线拍揄自揄视频不卡99| 久久婷婷综合激情| 亚洲欧美日韩国产另类专区| 国内偷自视频区视频综合| 亚洲精选中文字幕| 久久国产成人| 欧美日韩在线播放一区二区| 久久疯狂做爰流白浆xx| 欧美性做爰毛片| 亚洲国产一区在线| 欧美日韩国产综合新一区| 久久久欧美精品| 亚洲黄一区二区| 久久国产夜色精品鲁鲁99| 欧美激情亚洲自拍| 国产日韩欧美在线播放| 欧美在线综合视频| 亚洲自啪免费| 亚洲第一在线综合在线| 久久激情视频| 久久综合久久美利坚合众国| 欧美在线影院| 国产麻豆成人精品| 欧美日韩视频不卡| 亚洲第一久久影院| 欧美一区影院| 国产精品男人爽免费视频1| 蜜桃伊人久久| 噜噜噜噜噜久久久久久91 | 欧美国产日韩一区二区三区| 久久国产婷婷国产香蕉| 国产精品免费一区二区三区在线观看 | 久久色在线播放| 欧美成人一品| 久久天天躁狠狠躁夜夜爽蜜月| 国产欧美日韩一区二区三区在线 | 日韩午夜电影| 欧美a级一区二区| 欧美一级久久久久久久大片|