题目
20亿条字符串进行排序。每条字符串长度最大为255,字符范围为可见字符。
要求:最快的方法对其进行排序
分析
快排?归并?
何不试试字典树?
1) 应用场景:自动补全,拼写检查,
2) 时间复杂度为O(n)
代码
// Example program
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int gc_visibleCharNum = 92;
const int gc_beginCharIndex = 32;
class CDictTree
{
private:
char m_bChar;
bool m_isEnding;
CDictTree * m_pNext[gc_visibleCharNum];
public:
CDictTree()
{
m_bChar = 0;
m_isEnding = false;
for (int i = 0; i < gc_visibleCharNum; i++)
{
m_pNext[i] = nullptr;
}
}
// 插入单词(有点类似链表的插入):
// 1) node指向根节点
// 2) 从单词的第一个字符开始判断,该字符是否在节点指向的字母映射表中出现(不为nullptr空指针)
// 3) 如果没有出现过就创建对应的内存空间,然后node指向对应字母的链接。
// 4) 重复操作,直到该单词全部插入完,将最后的尾结点node->m_isEnding=true()(表示一个单词的结尾)。
int insert(string value)
{
CDictTree *pNode = this;
CDictTree *pNextNode = nullptr;
char c = 0;
size_t i = 0;
for (i = 0; i < value.length(); i++)
{
c = value[i];
pNextNode = pNode->m_pNext[c - gc_beginCharIndex];
if (nullptr == pNextNode)
{
pNextNode = new CDictTree();
pNextNode->m_bChar = c;
pNode->m_pNext[c - gc_beginCharIndex] = pNextNode;
}
pNode = pNextNode;
}
pNode->m_isEnding = true;
return 1;
}
// 查找单词是否在字典树中:
// 1) node先指向根节点,
// 2) 然后从单词的第一个字符开始判断,该字符是否在node指向的字母映射表中出现
// 3) 如果没有出现直接return false,否则node指向对应字母的链接,
// 4) 重复操作,直至单词全部查询完。
// 5) 最后再判断node->m_isEnding == true?
// 6) 如果不为true,则表示并不是单词的结尾(该单词没有出现在字典树中,只是前缀包含了该单词)。
int search(string value)
{
CDictTree *pNode = this;
CDictTree *pNextNode = nullptr;
char c = 0;
for (size_t i = 0; i < value.length(); i++)
{
c = value[i];
pNextNode = pNode->m_pNext[c - gc_beginCharIndex];
if (nullptr == pNextNode)
{
return false;
}
pNode = pNextNode;
}
return pNode->m_isEnding;
}
int DFS(CDictTree *tree, vector<string> *vec, string str)
{
if (tree != this)
{
str.append(1, tree->m_bChar);
if (tree->m_isEnding)
{
vec->push_back(str);
}
}
CDictTree *pNextNode;
for (int i = 0; i < gc_visibleCharNum; i++)
{
pNextNode = tree->m_pNext[i];
if (nullptr != pNextNode)
{
DFS(pNextNode, vec, str);
}
}
return 1;
}
};
int main()
{
string strs[10]={"he", "0him", "hello", "qian_xi", "We are famliy", "alibaba", "xutaiping", "CharlesKevin", "visiblechar", "!@#$%^&"};
vector<string> vecStr(strs,strs + 10);
// Build Tree
CDictTree tree;
for (vector<string>::iterator it = vecStr.begin(); it != vecStr.end(); it++)
{
tree.insert(*it);
}
// Search
for (vector<string>::iterator it = vecStr.begin(); it != vecStr.end(); it++)
{
printf("Search %s : %d\n", (*it).c_str(), tree.search(*it));
}
printf("Search Not Exist: %d\n", tree.search("What are u nong sha ne.."));
// DFS
vector<string> vecOrderStr;
tree.DFS(&tree, &vecOrderStr, "CharlesTest--");
for (vector<string>::iterator it = vecOrderStr.begin(); it != vecOrderStr.end(); it++)
{
cout<<*it<<endl;
}
return 0;
}
运行效果
关注 “CHARLESTEST-”的输出即可
Search he : 1
Search 0him : 1
Search hello : 1
Search qian_xi : 1
Search We are famliy : 1
Search alibaba : 1
Search xutaiping : 1
Search CharlesKevin : 1
Search visiblechar : 1
Search !@#$%^& : 1
Search Not Exist: 0
CharlesTest--!@#$%^&
CharlesTest--0him
CharlesTest--CharlesKevin
CharlesTest--We are famliy
CharlesTest--alibaba
CharlesTest--he
CharlesTest--hello
CharlesTest--qian_xi
CharlesTest--visiblechar
CharlesTest--xutaiping