contributed by < twngbm
>
首先創造一根節點,根節點必為空
@
我們試著插入單字and
@
/
a
/
n
/
d
再來我們試著插入單字 at
@
/
a
/ \
n t
/
d
中英文間請以空白隔開課程助教
以下示範插入and,at,be,bear,分別對應的value值為0,1,2,3
@
/ \
a b
/ \ \
n t e 2
/ 1 \
d a
0 \
r
3
從以上的結構,我們可以發現以下幾點事情。
我們可以從上面的例子發現,當元素的數量越大,trie所需的記憶體空間就會急遽上升,光是英文大寫字母的trie,每一個節點就會需要26個pointer,如果加上小寫數字和常用符號,trie的結構會變得非常大而不切實際。
因此我們介紹一種簡化版的trie ,Ternary search tree(TST),這種樹的每個節點最多只會有3個子節點,分別是小於,等於,大於。
以下範例示範ternary search tree
首先我們插入一值good,value=0,我們先拆分成g,o,o,d
基本概念跟trie一樣,但是這邊我們將 g 放入根節點
g
|
o
|
o
|
d
接著我們嘗試插入單字got
g
|
o
|
o—
| |
d t
接著我們嘗試插入單字goal
g
|
o
|
—o—
| | |
a d t
|
t
Key | Value |
---|---|
sur | 0 |
by | 4 |
shore | 7 |
the | 8 |
she | 10 |
sells | 11 |
are | 12 |
surely | 13 |
sea | 14 |
shells | 15 |
以下圖片示範TST
source code 的繁體中文翻譯為「原始程式碼」,有時會簡稱「源碼」(但不是「原」碼)
已修正
by :twngbm
- tst_ins_del(&root, &p, INS, CPY)
+ tst_ins_del(&root, &p, INS, REF)
改完後直接執行可以發現,S模式下,輸入的搜尋字串會一直重複。
進入函數tst_ins_del去觀察
if (*p++ == 0) {
const char *eqdata = strdup(*s);
if (cpy) { /* allocate storage for 's' */
if (!eqdata)
return NULL;
curr->eqkid = (tst_node *) eqdata;
return (void *) eqdata;
} else { /* save pointer to 's' (allocated elsewhere) */
curr->eqkid = (tst_node *) *s;
return (void *) *s;
}
}
發現傳入的REF=0,會進入281行執行,但是傳入的*s是單一個空間,因此會產生同一個空間一直重複的問題。
char tree[9000][WRDMAX];
while ((rtn = fscanf(fp, "%s", count)) != EOF) {
char *p = tree[count++];
傳入array後發現可以正確執行。