键树又称数字查找树,它是一棵度大于等于2的树,树中的节点不是包含一个或几个关键字,而只是包含组成关键字的符号。如果关键字是数值,则节点中的元素为一位的数字;如果关键字为字符,则节点中的元素为26个字符。如下是一棵键树。
从根节点到叶子结点路径上的元素组成一个关键字,其中叶子结点的特殊字符表示字符串的结束。
叶子节点中有指向关键字记录的指针。
为了查找的方便,我们约定同一层兄弟节点关键字从左到右有序。
键树的存储结构有两种:
1 用树的孩子--兄弟链表示键树(双链树)
每个分支节点有三个域:
first域:指向第一个孩子节点
symbol域:包含关键字字母字符
next域:指向兄弟节点
叶子结点中的infoptr域指向关键字记录。
typedef struct DLTNode{
char symbol;
struct DLTNode *next;
NodeKind kind;
union {
struct DLTNode *first;
Record *infoptr;
}
}
双链树查找规则如下:
从根节点开始,将待查字符串的第一个字符与first域中关键字比较,若相等,则继续将待查字符串的第二个关键字与子树根节点作比较;若不相等,则将待查字符串第一个字符与next域中的关键字相继作比较。
具体代码如下:
#define maxlenth 20;
typedef enum{left,branch}NodeKind;
typedef struct DLTNode{
char symbol;
struct DLTNode *next;
NodeKind *kind;
union{
struct DLTNode* first;
string *infoptr;
};
}*DLTree;
struct KeyType{
char a[20];
int num;
};
string *SearchChar(DLTree T, KeyType k){
int i = 0;
DLTNode* p = T->first;
while (p && i < k.num){
if (k.a[i] == p->symbol){
i++;
p = p->first;
}
else{
p = p->next;
}
}
if ( i == k.num){
return p->infoptr;
}
else{
return NULL;
}
}
2 Trie树(字典树)
如果以多重链表表示键树,则每个节点包含d个指针域(d为关键字字符的基,假如关键字为字符,则d为26),此时的键树又称为Trie树。
Trie树中含有两种节点:
分支节点:含有d个指针域以及记录节点中非空指针域节点个数的整数域。每个分支节点所表示的关键字与其父节点中指向该节点的指针所在的位置决定。
Trie树中节点结构如下:
Trie树表示的树结构:
查找关键字代码如下:
#define maxlenth 20;
typedef enum{left,branch}NodeKind;
struct KeyType{
char a[20];
int num;
};
typedef struct TrieNode{
NodeKind kind;
union{
struct { KeyType k; string *infoptr; }lef;
struct{ TrieNode *ptr[27]; int num; }bh;
};
}*TrieTree;
int ord(char a){
int b = a - 46;
return b;
}
string *SearchChar(TrieTree T, KeyType K){
int i = 0;
TrieTree p = T;
while (i < K.num){
if (p && p->kind==branch && p->bh.ptr[ord(K.a[i])]){
i++;
p = p->bh.ptr[ord(K.a[i])];
}
else{
return NULL;
}
}
if (p ){
return p->lef.infoptr;
}
}