字典树的数据结构我就不作描述了,网上的Trie算法基本上都是基本字符串作为KEY的,字符串作为KEY每个子节点占用26 * 4个字节,对于数据量不大的情况效果不错,但对于大量数据占用内存空间消耗比较大,而使用数值作为KEY的话每个节点仅点10 * 4个字节,相对于字符串来说浪费的空间得到很大改善了。直接上代码!
template <class Type>
class CTrie
{
struct Node
{
Type Val;
bool isLeaf; //是否叶节点
Node *parent;
Node *childs[10];
Node()
{
isLeaf = false;
parent = NULL;
Val = Type();
for (int i = 0; i < 10; i++)
{
childs[i] = NULL;
}
}
};
protected:
Node * m_root;
size_t m_size;
public:
CTrie()
{
m_size = 0;
m_root = new Node();
}
~CTrie()
{
clear();
delete m_root;
}
//插入键值
void insert(DWORD dwKey, const Type &Val)
{
if (!m_root) return;
Node *node = m_root;
int index;
do
{
index = dwKey % 10;
if (!node->childs[index])
{
node->childs[index] = new Node();
node->childs[index]->parent = node;
}
node = node->childs[index];
dwKey /= 10;
} while (dwKey > 0);
node->isLeaf = true;
node->Val = Val;
m_size++;
}
//键值查找
bool find(DWORD dwKey, Type &Val)
{
if (!m_root) return false;
Node *node = m_root;
int index;
do
{
index = dwKey % 10;
node = node->childs[index];
dwKey /= 10;
} while (dwKey > 0 && node);
if (node)
{
Val = node->Val;
return true;
}
return false;
}
//移除键值
void erase(DWORD dwKey)
{
if (!m_root) return;
Node *node = m_root;
int index;
do
{
index = dwKey % 10;
node = node->childs[index];
dwKey /= 10;
} while (dwKey > 0 && node);
if (node)
{
m_size--;
node->isLeaf = false;
node->Val = NULL;
Node *parent;
do
{
if (m_root == node)
break;
parent = node->parent;
if (!hasChild(node))
{
if (node->parent)
{
for (int i = 0; i < 10; i++)
{
if (node->parent->childs[i] == node)
{
node->parent->childs[i] = NULL;
break;
}
}
}
delete node;
}
else
{
break;
}
node = parent;
} while (node);
}
}
size_t size()
{
return m_size;
}
bool empty()
{
return (m_size == 0);
}
void clear()
{
if (!m_root) return;
for (int i = 0; i < 10; i++)
{
if (m_root->childs[i])
{
removeChild(m_root->childs[i]);
m_root->childs[i] = NULL;
}
}
m_size = 0;
}
private:
bool hasChild(Node *node)
{
if (!node) return false;
for (int i = 0; i < 10; i++)
{
if (node->childs[i])
{
return true;
}
}
return false;
}
void removeChild(Node *node)
{
if (!node) return;
for (int i = 0; i < 10; i++)
{
if (node->childs[i])
removeChild(node->childs[i]);
}
delete node;
}
//反序KEY
DWORD reverseKey(DWORD dwKey)
{
if (dwKey == 0) return 0;
DWORD dwValue = 0;
do
{
dwValue = dwValue * 10 + dwKey % 10;
dwKey /= 10;
} while (dwKey > 0);
return dwValue;
}
};