用二叉樹實現Trie樹

2021-06-22 11:55:29 字數 3220 閱讀 9555

1.引言

trie樹是一種快速查詢樹,關於trie樹的特性和優點,這裡就不再羅嗦了,請參照這篇文章:trie樹實現詞典查詢演算法。在此文中,trie樹的實現用的是二十六叉樹,理解起來直觀易懂,演算法也簡單明瞭,但是有乙個致命的弱點,就是浪費空間。特別是在資料規模比較小的情況下,資料稀疏問題表現的特別嚴重。因此需要進行改進。二十六叉樹浪費空間的原因是有好多被分配的空間上實際上沒有資料,但是trie樹的節點結構是在建立乙個節點時就預設分配了指向其二十六個孩子的指標,即便是該節點僅有乙個孩子,它也會有這二十六個指標,因此會造成極大的空間浪費。

「任何森林都可以轉換為二叉樹」。將多叉樹轉成二叉樹非常容易,簡單說就是「左兒子,右兄弟」。就是將乙個節點的第乙個兒子放在左兒子的位置,下乙個兒子,即左兒子的第乙個兄弟,放在左兒子的右兒子位置上,再下乙個兄弟接著放在右兒子的右兒子的位置。看下面的圖,就更清楚了。左邊是多叉樹,右邊是轉換後的二叉樹。

下面將trie樹的演算法改造為用二叉樹來實現,同樣實現如下的功能:

隨機產生10w個字串,字串的長度在10~30之間,以這10w個數為單詞構建詞典,詞典用二叉樹實現的trie樹進行儲存。(1)實現詞典的檢索功能;(2)將這10w個詞拼成乙個大的字串a,實現乙個多模匹配演算法,尋找詞典中的詞在字串a中出現了多少次(很明顯,最少為一次)。

2.時間複雜度分析

下面的演算法的執行結果如下,從中可以看出,在長字串中搜尋字串,即多模式匹配的時間耗費很大,時間約為35分鐘,其時間複雜度為mn(m為長字串的長度,n為單詞的最大長度),還需要進一步改進。

(1)建立trie樹用時(納秒):441412

(2)查詢字串用時(納秒):4

(3)在長字串中搜尋短字串用時(納秒):2090213036

3.源**

好了,下面上演算法:

#include #include #include #include #include #include using namespace std;

//---------------trie樹的定義及實現部分----------------

//節點的定義

class node

node(char c) : index(c), word(""), flag(0), count(0)

};//trie樹的操作定義

class trie;

trie::trie()

trie::~trie()

//插入新的字串

void trie::insert(string str)else if(cur != null && cur -> index > str[i])else

if(cur != null && cur -> index == str[i])else

} }if(pre -> flag == 1)else

}//搜尋字串

bool trie::search(string str, int &count)

if(cur != null && cur -> index == str[i])else

}else

} if(cur -> flag == 1)else

}//列印節點內容

void trie::print(node *proot)

print(proot -> right);

print(proot -> left);

}else

}//列印整棵樹

void trie::printall()

//特殊的搜尋字串(特殊用法)

void trie::search_2(string str)

if(cur != null && cur -> index == str[i])

}else

}else }}

//----------------------測試部分----------------------------

//獲取當前時間(納秒)

long getcurrenttime()

//主函式

int main()

//2.建立trie樹

long time_1 = getcurrenttime();

while(getline(fin, str, '\n'))

long time_2 = getcurrenttime();

fin.close();

//3.驗證trie樹的正確性

fin.open("dict.txt");

while(getline(fin, str, '\n'))else

} fin.close();

//4.普通查詢

int count = -1;

str = "pfpqefqdbjbmywz";

long time_3 = getcurrenttime();

bool isfind = trie.search(str, count);

long time_4 = getcurrenttime();

if(isfind)else

//5.將短字串組合為長字串

string long_str;

ostringstream string_out;

fin.open("dict.txt");

while(getline(fin, str, '\n'))

long_str = string_out.str();

//6.在長字串中搜尋字典中的字串

long time_5 = getcurrenttime();

cout << long_str.size() << endl;

for(int i = 0; i < long_str.size()-30; i++)

long time_6 = getcurrenttime();

//5.列印字典中的所有詞以及出現次數

trie.printall();

//8.列印各項任務時間

cout << "建立trie樹用時(納秒):" << time_2 - time_1 << endl;

cout << "查詢字串用時(納秒):" << time_4 - time_3 << endl;

cout << "在長字串中搜尋短字串用時(納秒):" << time_6 - time_5 << endl;

}

用二叉樹實現排序

package com.huang public class nodetree 實現 有序二叉樹 nodetree nodetree newnodetree for int i 0 i nodetree.inorder 輸出中序遍歷結果 nodetree.preorder 前序遍歷 nodetree...

用JS實現二叉樹

用js實現二叉樹資料結構,完成遍歷 查詢最大 小值 查詢特定值以及刪除節點的操作。參考博文 定義節點 class node 建立二叉搜尋樹 bst class binarysearchtree 插入節點 insert data else else else if this root else 中序遍...

樹 二叉樹 滿二叉樹 完全二叉樹 完滿二叉樹

目錄名稱作用根 樹的頂端結點 孩子當遠離根 root 的時候,直接連線到另外乙個結點的結點被稱之為孩子 child 雙親相應地,另外乙個結點稱為孩子 child 的雙親 parent 兄弟具有同乙個雙親 parent 的孩子 child 之間互稱為兄弟 sibling 祖先結點的祖先 ancesto...