空間優化的字典樹
阿新 • • 發佈:2019-02-18
字典樹空間優化
如果字典樹要儲存的字串的字符集比較大,(比如全部的字元),甚至可能有多位元組字元。這是我們給每個節點256個子節點嗎? 用平衡樹(或map <char, int>
)犧牲時間來換取空間嗎?
不,可以進行這樣的優化: 我們考慮把一個8位的char,拆開變成2個4位的資料,依次加入字典樹。顯然4位最大值也只是2^4-1=15,每個節點只需要16個子節點。 當然這樣做相當於字串長度len *= 2
,時間 *= 2
。但是如果原先需要的空間為m,這樣優化後的空間只需要2*sqrt(m)
,大幅度減小了空間佔用。而時間並沒增大很多。
下面給出一份實現程式碼
#ifndef TRIE_H
#define TRIE_H
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "basedef.h"
#define NEXT_SIZE 16
typedef struct trieNodeType
{
bool isFinal;
struct trieNodeType *(*next);
}trieNode, *pTrieNode;
typedef struct trieType
{
trieNode *root;
}trie;
void initTrie(trie *t)
{
t -> root = (trieNode *)malloc(sizeof(trieNode));
memset(t -> root, 0, sizeof(trieNode));
}
trieNode *appendChar(trieNode *d, int t)
{
if(!d -> next)
{
d -> next = (pTrieNode *)malloc(sizeof(pTrieNode) * NEXT_SIZE);
memset(d -> next, 0 , sizeof(pTrieNode) * NEXT_SIZE);
}
if(!d -> next[t])
{
d -> next[t] = (pTrieNode)malloc(sizeof(trieNode));
memset(d -> next[t], 0, sizeof(trieNode));
}
return d -> next[t];
}
void insertWord(trie *t, char *w, int len)
{
trieNode *fw = t -> root;
for(int i = 0; i < len; i++)
{
unsigned char c = w[i];
unsigned hw = (c & (unsigned char)0xf0)>>4; //高四位
unsigned lw = c & (unsigned char)0x0f; //低四位
fw = appendChar(fw, hw);
fw = appendChar(fw, lw);
}
fw -> isFinal = true;
}
bool existWord(trie *t, char *w, int len)
{
trieNode *fw = t -> root;
for(int i = 0; i < len; i++)
{
if(!fw -> next)
return false;
unsigned char c = w[i];
unsigned hw = (c & (unsigned char)0xf0)>>4;
unsigned lw = c & (unsigned char)0x0f;
if(fw -> next[hw])
fw = fw -> next[hw];
else return false;
if(fw -> next[lw])
fw = fw -> next[lw];
else return false;
if(!fw)return false;
}
return fw -> isFinal;
}
void destroyTrieNodes(pTrieNode d)
{
if(!d)return;
if(!d -> next)return;
for(int i = 0; i < NEXT_SIZE; i++)
if(d -> next[i])destroyTrieNodes(d -> next[i]);
for(int i = 0; i < NEXT_SIZE; i++)
if(d -> next[i])free(d -> next[i]);
free(d -> next);
}
void destroyTrie(trie *t)
{
destroyTrieNodes(t -> root);
}
#endif