1. 程式人生 > >空間優化的字典樹

空間優化的字典樹

字典樹空間優化

如果字典樹要儲存的字串的字符集比較大,(比如全部的字元),甚至可能有多位元組字元。這是我們給每個節點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