问题简介:
键树,又称数字查找树。它是一棵度>=2的树,树中的每个结点只含有组成关键字的某个符号。例如,如果关键字是数值,则一个结点中只包含一个数位;若关键字是单词,则一个结点只包含一个字母。每个完整的关键字都是从根节点到叶子结点所经过的所有结点的组合。这种特殊的树会给某些类型的关键字的表的查找带来方便。
示意图:
例如,一组单词集合为{CAR,CAT,CAKE,LIKE,LIE,WHEN,WE},则根据键树的定义,先将首字母相同的单词进行组合:{{CAR,CAT,CAKE} , {LIE,LIKE} , {WE,WHEN}}
若所得子集的关键字多余一个,则还需按照后一个字母继续分割,知道每个小子集只包含一个关键字。最后所得结果如图所示:
为了操作方便,我们规定键树在同一层中符号从左到右有序,并且结束符$小于任何字符。
键树的储存结构
键树有两种储存结构,分别是以树的孩子兄弟链表来表示的双链树,和以多重链表来表示的Trie树。
双链树
此时每个分支节点有三个域:symbol域,用于存储当前的字符;first域,用于指向第一棵子树的根的指针;next域,用于指向右兄弟的指针。同时,叶子结点还有一个单独的infoptr域,用于储存指向该关键字记录的指针。
储存结构代码:
#define MAXKEYLEN 16 //关键字的最大长度
typedef struct{
char ch[MAXKEYLEN]; //关键字
int num; //关键字的长度
}KeysType; //关键字的类型
typedef enum {LEAF, BRANCH} Nodekind; //结点种类,分为叶子和分支
typedef struct DLTNode{
char symbol;
struct DLTNode *next; //指向兄弟结点
NodeKind kind;
union{
Record *infoptr; //叶子结点的记录指针
struct DLTNode *first; //指向孩子结点
}
}DLTNode, *DLTree;
进行查找时,按照如下规则执行:假设需要查找的关键字为K.ch(0...n-1),其中K.ch[0]到K.ch[n-2]代表关键字所含的n-1个字符,而K.ch[n-1]为结束符$。从双链树的根节点出发,顺着first域查找当前结点的第一颗子树的根节点,比较K.ch[i]与当前symbol域的值是否相同,如果相同,则继续将指针移到下一个first域,否则,则通过next域查找兄弟结点。若直至兄弟结点查找完都为不等,则查找失败。
查找算法代码:
Record *SearchDLtree(DLTree T,KeyType K){
DLTree p=T->first; //指针指向第一个结点
int i=0;
while(p && i<K.num){
while(p&&p->symbol!=K.ch[i]) p=p->next; //查找关键字的第i位
if(p && i<K.num-1) p=p->first; 当前位查找到,准备查找下一位
i++;
}
if(!p) return NULL; //查找成功
else return p->infoptr; //查找失败
}
Trie树
Trie树又称字典树,树里的每个节点都含有d个指针域。
其中,d表示最大度,它域关键字的类型有关。如果关键字由字母组成,则d为26个字母加上一个$结束符等于27,同样道理得,数字的d为11。
若从Trie树的某个节点到叶子结点的路径上每个结点都只有一个孩子,则将该路径上的所有结点压缩成一个叶子节点,且在该叶子节点中存储关键字及指针等信息。
储存结构代码:
typedef struct TrieNode{
NodeKind kind;
union{
struct{KeysType K;Recond *infoptr;} lf; //叶子结点
struct{TrieNode *ptr[27];int num;} bh; //分支结点
};
}TrieNode,*TrieTree;
查找时,从根节点出发,沿着对应的指针逐层向下,直到叶子结点,若叶子节点的关键字与给定值线条灯,则成功查找。若叶子节点中的关键字和给定值不相等或分支节点中和给定值相应的指针为空,则不成功。
查找算法代码:
Record *SearchTrie(TrieTree T,KeysType K){
for(p=T,i=0;
p && p->kind==BRANCH && i<K.num; //p为分支节点
p=p->bh.ptr[ord(K.ch[i])],++i); //ord求字符在字母表中的序号
if(p && p->kind==LEAF&&p->lf.K==K) //查找成功
return p->lf.infoptr; //查找失败
else return NULL;
}
以上就是关于键树查找的简单介绍