1. 程式人生 > >【模板】Trie樹模板

【模板】Trie樹模板


Trie樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計,排序和儲存大量的字元(但不僅限於字串),所以經常被搜尋引擎系統用於文字詞頻統計。

上面是百度百科找的,trie樹=字典樹=字首樹,下面就說說字首樹的實現。


首先trie樹的根必定是一個空節點,每一條邊代表了一個字元,每一個節點有多種可能,那麼我們可以使用一個數組來達到這個目的;

同時,每一個單詞(字串)的最後一個字元所指向的節點需要做標記(如上圖的紅色節點),以表示從樹根到現在所遍歷的一個字串;

那麼上面所說的就可以通過一個結構體來實現。

int num = 26;  //以26個小寫字母為例
struct TrieNode
{
	bool isTri;
	TrieNode *next[num];
};
然後這個trie就需要插入字串,刪除節點,以及查詢字串,當然,插入字串的函式或者搜尋字串也可以用來刪除某一字串;插入字串,從根節點開始,依次遍歷字串中的每一個字元,同時也建立新的節點,以達到插入的目的,下面是程式碼的實現:

void Insert(TrieNode* root,const char* word)
{
	TrieNode *now = root;
	while(*word)
	{
		if(now->next[*word-'a']==NULL)              //*word-'a'用於表示某一字元的位置
		{
			TrieNode *newNode = new TrieNode();
			newNode->isTri = false;
			newNode->yes = 0;
			memset(newNode->next,NULL,sizeof(newNode->next));
			
			now->next[*word-'a'] = newNode;
		}
       now = now->next[*word-'a'];
 	   word++; 
	}
	now->isTri = true;
}


搜尋字串,也是從根節點開始,依次遍歷,直到樹的最深處或者到達字串的最後一個字元為止,在這個時候就可以如果到達數的最深處的時候字串仍然沒有遍歷完,或者遍歷完最後一個字元的時候這個加點未被標記,那麼我們就可以返回false的資訊,表示沒有搜尋到;反之,如果遍歷字串結束之後並且此時的節點被標記(儲存過該字串),則返回true的資訊,當然搜尋這裡還有部分的應用,這裡就不說了。

bool Search(TrieNode* root,const char* word)
{
	TrieNode *now = root;
	while(*word)
	{
		if(*word&&now != NULL)
		{
			now = now->next[word-'a'];
			word++;
		}
	}
	return (now->isTri&&now!=NULL);
}

刪除節點,就是使用遞迴的方式刪除節點,從某一節點開始,依次遍歷其所有節點,又繼續刪除;

void Delete(TrieNode* node)
{
	for(int i = 0;i<num;i++)
	{
		if(node->next[i]!=NULL)
		{
			Delete(node->next[i]);
		}
	}
	delete node;
}


完整程式碼:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int num = 26;



struct TrieNode
{
	bool isTri;
	TrieNode *next[num];
}


void Insert(TrieNode* root,const char* word)
{
	TrieNode *now = root;
	while(*word)
	{
		if(now->next[word-'a']==NULL)
		{
			TrieNode *newNode = new TrieNode();
			newNode->isTri = false;
			memset(newNode->next,NULL,memset(newNode->next));
			
			now->next[word-'0'] = newNode;
		}
       now = *newNode;
 	   word++; 
	}
	now->isTri = true;
}

bool Search(TrieNode* root,const char* word)
{
	TrieNode *now = root;
	while(*word)
	{
		if(*word&&now != NULL)
		{
			now = now->next[word-'a'];
			word++;
		}
	}
	return (now->isTri&&now!=NULL);
}

void Delete(TrieNode* node)
{
	for(int i = 0;i<num;i++)
	{
		if(node->next[i]!=NULL)
		{
			Delete(node->next[i]);
		}
	}
	delete node;
}
int main()
{
	TrieNode *root = new TrieNode();
	root->isTri = false;
	memset(root->next,NULL,sizeof(root->next));
	//主函式就不寫了,這裡就是應用資料結構的地方,交代一下根節點的初始化即可 
	return 0;
}