Trie 树的简单实现

来源:互联网 发布:js获取img的alt 编辑:程序博客网 时间:2024/06/05 17:32

Trie tree Wikipedia

Trie 树, 又称前缀树,是一种高校的动态存储结构

查找效率:O(m)   m为串的长度

空间要优于BST(二叉搜索树),因为Trie 树是前缀复用的。

实现了插入、删除、显示

加了注释,另外析构函数没有实现,释放树资源的函数也没有实现 :(

#define CHARSIZE 26#include<assert.h>#include<stdlib.h>#include<iostream>using namespace std;/*树节点,用于存储当前字符信息*/typedef struct NODE {char key;//该值可以没有,由于程序的,可以注释掉相关代码bool isNode;//当前节点代表的字符串是否是存入的节点struct NODE* child[ CHARSIZE ];//26叉树,按照a-z的顺序,如果是NULL表示该字母位置为空}* PNODE,*TRIE;class Trie{public:Trie();void Insert( char* sData );void Show( );void ShowTrie( PNODE root );bool Delete( char* sData );bool NoChild(PNODE pNode);struct NODE* Search( char* sData );void DeleteTrie();~Trie();private:PNODE pRoot;//树指针 static char colls[];//代表26个字母,可以设置自定义的映射和长度};char Trie::colls[] = "abcdefghijklmnopqrstuvwxyz ";/*构造函数,创建根节点*/Trie::Trie(){//root createthis->pRoot = NULL;this->pRoot = (PNODE)malloc(sizeof(struct NODE));this->pRoot->key = ' ';this->pRoot->isNode = false;for( int i=0; i<CHARSIZE; i++ ){this->pRoot->child[ i ] = NULL;}}/*插入新节点*/void Trie::Insert( char* sData ){//如果字符串为空,不允许插入if( sData==NULL || *sData == '\0' ){return;}//获取根指针,用于后边的查找正确的插入位置PNODE p = this->pRoot;char* pData = sData;//当前字符指针//循环直到处理完所有字符while( *pData!='\0' ){//如果对应位置的指针为空,就创建新的节点if( p->child[ *pData-'a' ]==NULL ){//make new NodePNODE node = (PNODE)malloc(sizeof(struct NODE));//node->key = *pData;//key是多余的字段node->isNode = true;//该新节点表示真正的存储节点而不是前缀int i = 0;while( i < CHARSIZE ){node->child[i] = NULL;i++;}//将新节点链接到树中的合适位置p->child[*pData-'a'] = node;}//go on loopp = p->child[ *pData-'a' ];//deal with next characterpData++;}}/*Show string stored in Trie tree:( not look well, but you can draw on paper from this outputor whtn you delete one node, you will see the change*/void Trie::Show( ){//为了便于递归调用,使用中间函数ShowTrie( this->pRoot );}void Trie::ShowTrie( PNODE root ){if( root==NULL ){return;}if( root->isNode == true )cout<<root->key<<"";for( int i=0; i<CHARSIZE; i++ ){ShowTrie( root->child[i] );}}/*Delete node from Trie tree*/bool Trie::Delete( char * sData ){if( sData==NULL || *sData=='\0' )return false;PNODE p = this->pRoot;PNODE pre = NULL;char *pData = sData;while(pData!=NULL && *pData!='\0'){if( p==NULL || p->child[*pData-'a']==NULL ){cout<<"No:"<<*sData<<endl;}else if( p->child[*pData-'a']->isNode==true ){//delete thisif( NoChild(p->child[*pData-'a']) ){p->child[*pData-'a'] = NULL;//delete this node directly}else{//has childrenp->child[*pData-'a']->isNode = false;}return true;}else{pre = p;p = p->child[*pData-'a'];pData++;}}return false;}/*Is a node has children*/bool Trie::NoChild(PNODE pNode){if(pNode == NULL)return true;for( int i=0; i<CHARSIZE; i++ ){if( pNode->child[i]!=NULL ){return false;}}return true;}void Trie::DeleteTrie(){}Trie::~Trie(  ){}

主程序:

#include<iostream>#include"trie.h"using namespace std;int main( int argc, char* argv[] ){Trie myTrie = Trie();myTrie.Insert( "a" );myTrie.Insert( "ab" );myTrie.Insert( "ac" );myTrie.Insert( "ad" );myTrie.Insert( "ae" );myTrie.Insert( "af" );myTrie.Insert( "abc" );myTrie.Insert( "abe" );myTrie.Insert( "abf" );myTrie.Insert( "add" );myTrie.Insert( "bb" );myTrie.Insert( "bh" );myTrie.Show();cout<<endl;myTrie.Delete("bb");myTrie.Show();cout<<endl;myTrie.DeleteTrie();return 0;}