第15章 基数搜索
一些搜索方法的处理办法是一次一个小片段地检查搜索键,而不是每一步在键之间进行全面比较。这些方法称做基数搜索方法(radix-search mothod),它们的运算方式与基数排序方式完全类似。当搜索键片段易于访问时,这些方法非常有效,而且它们可以为各种实际搜索任务提供高效的解决方案。
根据上下文的不同,键可能为字(定长字节序列)或者是串(变长字节序列)。我们将字键看作为以R为基数的数值系统中表示的数,R值(即基数)可以不同,再处理数值的单个位。可以将C串看作以特殊符号终止的变长数值。因此,对于定长或变长键,我们可以让所有的算法以抽象运算“从键中提取第i个位”为基础,还包括一条处理键少于i个位的情况的约定。
基数搜索方法的主要优点是,它们提供了最坏情况的合理性能,而不必使用复杂的平衡树;它们提供了处理变长键的简单方式;某些方法可以在搜索结构中排序部分键以节省空间;它们还提供了数据的快速访问,其速度可以与二叉搜索树与哈希方法匹敌。缺点是,某些方法低效使用空间,而且像基数排序一样,如果不能有效地访问键的字节,性能可能会下降。
15.1 位搜索树
最简单的基数搜索方法是基于位搜索树(digital search tree, DST)的运用。搜索和插入算法等同于二叉搜索树,唯一的区别是:不是根据完全键间的比较结果,而是根据选定的键位让树分支。在第一层,使用前导位;在第二层,使用第二前导位;依次类推,直到碰到一个外部节点。
15.1.1 位搜索树的操作
typedef struct Node *link;
//DST
struct Node{
Item item;
link l;
link r;
};
void Init()
{
head = z = NEW(0,0,0);
}
link NEW(Item v, link l, link r)
{
link x = (link)malloc(sizeof(*x));
x->l = l;
x->r = r;
x->item = v;
return x;
}
15.1.1.1 位搜索树的插入操作
/*
位搜索树的插入操作根据对应位为0还是为1来决定新插入项为左孩子还是右孩子
*/
link Insert(link h, Item v, int w)
{
if (z == h) return NEW (v,z,z);
Key tempkey = key(h->item);
if (digit (v, w) == 0)
{
h->l = Insert(h->l, v, w + 1);
} else {
h->r = Insert(h->r, v, w + 1);
}
return h;
}
void RSInsert(Item v)
{
head = Insert (head, v, 0);
}
15.1.1.2 位搜索树的查找操作
/*
在此程序中,不是进行完全键比较,而是在键的单个位(前导位)测试的基础上决定是否从左移到右。这个递归调用函数有第三个参数,当沿树下移时,我们可以将被测试的位移到右边。使用digit运算来测试位。
*/
Item searchR(link h, Item v, int w)
{
Key t = key(h->item);
if (h == z) return NULLitem;
if (eq(v, t)) return h->item;
if (digit(v, w) == 0)
{
return searchR(h->l, v, w + 1);
} else {
return searchR(h->r, v, w + 1);
}
}
Item RSsearchR(Item v)
{
return searchR (head, v, 0);
}
15.1.1.3 位搜索树的性能分析
l 请注意,DST没有BST所特有的有序性。也就是说,不是必须让已知节点左边的节点具有较小的键,或右边的节点具有较大的键,而在具有不同键的BST中要求如此。已知节点左边的键小于右边的键(如果节点在k层,则它们都与第k个位一致,但左边的下一位为0,右边键的下一个位为1),不过,节点的键本身可能在该节点子树的所有键中为最小、最大或任意值。
l DST具有以下特征:每个键在沿着键的位所指定路径(按从左到右顺序)的某个地方。
l 如果键数庞大而且键长相对于键数较小时,位搜索生成树的最坏情况比二叉搜索树要好得多。在一棵位搜索树中,最长路径的长度可能在许多应用中相当短(例如,如果键包含随机位的时候)。特别是,最长路径要受到最长键的限制;而且,如果键为定长,则搜索时间受长度的限制。
l DST在许多实际应用中时理想的方法,因为它们即使对于大型问题,也能通过很少的代码实现近最优的性能。例如,一棵根据32位键(或4个8位字符)生成的位搜索树能确保只需要32次以下的比较,一棵根据64位键(或8个8位字符)生成的位搜索树能确保需要64次以下的比较,即使多达几十亿个键也是如此。对于大