动态表查找的特点是:表结构本身在查找过程中动态生成。
包括:
二叉排序树(BinarySortTree)或二叉搜索树(BinarySearchTree),平衡二叉树、B-树和B+树,键树
1.二叉排序树
2.平衡二叉树
3.B-树
//B-Tree.c
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define m 3 //定义B-树的阶数
typedef int Boolean;
typedef int KeyType; //定义关键字类型
typedef char InfoType; //定义记录中除关键字外其它数据的类型
typedef struct { //定义记录类型
KeyType key;
InfoType otherinfo;
}RedType;
typedef struct BTNode{ //定义B-树中结点类型(非叶子结点)
int keynum;//结点中关键字个数
struct BTNode *parent;//指向双亲结点
KeyType key[m + 1];//定义关键字向量,0号单元未用
struct BTNode *ptr[m + 1];//子树指针向量
RedType *recptr[m + 1];//记录指针向量,0号单元未用
}BTNode, *BTree;
typedef struct{//定义B-树查找结果类型
BTNode *pt;//指向找到的结点
int i;//1...m,在结点中的关键字序号
int tag;//1:查找成功,0:查找失败
}Result;
//此函数用来在B-树中查找关键字key
Result SearchBTree(BTree T, KeyType key){
//在m阶B-树T上查找关键字key,返回结果Result。
//若查找成功,则特征值tag=1,指针pt所指结点中第i个关键字等于key;
//若查找失败,则特征值tag=0,等于key的关键字应插在指针pt所指结点中第i和第i+1个关键字之间。
int i=0;
Boolean found=FALSE;
BTree p, q;
Result result;
p = T; //p指向待查结点
q = NULL; //q指向p的双亲
while (p&&!found){
i = Search(p, key);//在p->key[1...keynum]中查找,i使得p->key[i]<=key<p->key[i+1]
if (i > 0 && p->key[i] == key)
found = TRUE;//找到待查关键字
else{
q = p;
p = p->ptr[i];
}
if (found){
result.pt = p;
result.i = i;
result.tag = 1;
return result;
}
else{
result.pt = q;
result.i = i;
result.tag = 0;
return result;
}
}
}
// 此函数在B-树上插入一个关键字
Boolean InsertBTree(BTree T, KeyType key, BTree q, int i){
//在m阶B-树T上结点*q的key[i]与key[i+1]之间插入关键字key
//若引起结点过大,则沿双亲链进行必要的结点分裂调整,使T仍是m阶B-树
KeyType x = key; //x进行关键字的迭代
BTree ap = NULL; //ap指向新结点
Boolean finished = FALSE; //标识是否插入完成
int s;//数组下标
while (q&&!finished){
Insert(q, i, x, ap);//将x和ap分别插入到q->key[i+1]和q->ptr[i+1]
if (q->keynum < m)
finished = TRUE;//插入完成
else{
s = floor(m / 2);
split(q, s, ap);
x = q->key[s];
/*
(此处过程omit)
将q->key[s+1...m],q->ptr[s...m]和q->recptr[s+1...m]移入新结点*ap
*/
q = q->parent;//q上移到双亲结点
if (q){
i = Search(q, x);//在双亲结点*q中查找x的插入位置
}
}
}
if (!finished) //T是空树(参数q初值为NULL)或者根结点已分裂为结点*q和*ap
NewRoot(T, q, x, ap);//生成含信息(T,x,ap)的新结点*T,原T和ap为子树指针
return TRUE;
}
4.键树
键树又称数字查找树(Digital Search Trees)。
键树有两种存储结构:
(1)双链树
(2)多重链表键树。(Trie Tree)
(1)双链树
//双链树
#include <stdio.h>
#include <stdlib.h>
#define MAXKEYLEN 16 //定义关键字最大长度
typedef struct{ //关键字类型
char ch[MAXKEYLEN]; //关键字
int num; //关键字长度
}KeyType;
typedef enum{ LEAF, BRANCH } NodeKind; //结点种类:叶子,分支
typedef char InfoType; //定义记录中除关键字外其它数据的类型
typedef struct { //定义记录类型
KeyType key;
InfoType otherinfo;
}RedType;
typedef struct DLTNode{ //定义双链树结点类型
char symbol;
struct DLTNode *next; //指向兄弟结点的指针
NodeKind kind;
union {
RedType *infoptr; //叶子结点的记录指针
struct DLTNode *first; //分支结点的记录指针
};
}DLTNode, *DLTree;
//在双链树中查找记录
RedType *SearchDLTree(DLTree T, KeyType key){
//在非空双链树T中查找关键字等于key的记录。若存在,则返回指向该记录的指针,否则返回空指针。
DLTree p;
p = T->first;
int i = 0;
while (p&&i<key.num){
while (p&&p->symbol != key.ch[i])//查找关键字的第i位
p = p->next;
if (p&&i < key.num - 1)//准备查找下一位
p = p->first;
i++;
}
if (!p)
return NULL; //查找不成功,返回NULL
else
return p->infoptr;//查找成功,返回指向该记录的指针
}
(2)Trie 树
//TrieTree.c
#include <stdio.h>
#include <stdlib.h>
#define MAXKEYLEN 16 //定义关键字最大长度
typedef struct{ //关键字类型
char ch[MAXKEYLEN]; //关键字
int num; //关键字长度
}KeyType;
typedef enum{ LEAF, BRANCH } NodeKind; //结点种类:叶子,分支
typedef char InfoType; //定义记录中除关键字外其它数据的类型
typedef struct { //定义记录类型
KeyType key;
InfoType otherinfo;
}RedType;
typedef struct TrieNode{//Trie树结点类型定义
NodeKind kind;
union{
struct {
KeyType key;
RedType *infoptr;
}leaf;//叶子结点
struct {
TrieNode *ptr[27];
int num;
}branch;//分支结点
};
}TrieNode, *TrieTree;
//此函数在Trie Tree中查找等于关键字key的记录
RedType *SearchTrie(TrieTree T, KeyType key){
TrieTree p;
int i = 0;
for (p = T, i = 0; p && p->kind == BRANCH && i < key.num; i++)//对key的每个字符逐个查找
p = p->branch.ptr[ord(key.ch[i])];//ord()函数求字符在字母表中的序号
if (p && p->kind == LEAF && p->leaf.key == key)//查找成功
return p->leaf.infoptr;
else
return NULL;
}