TSEARCH - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-06-09
名称
tsearch,tfind,tdelete,twalk,tdestroy-管理二进制搜索树
语法
#include <search.h> typedef enum { preorder, postorder, endorder, leaf } VISIT; void *tsearch(const void *key, void **rootp, int (*compar)(const void *, const void *)); void *tfind(const void *key, void *const *rootp, int (*compar)(const void *, const void *)); void *tdelete(const void *key, void **rootp, int (*compar)(const void *, const void *)); void twalk(const void *root, void (*action)(const void *nodep, VISIT which, int depth)); #define _GNU_SOURCE /* See feature_test_macros(7) */ #include <search.h> void twalk_r(const void *root, void (*action)(const void *nodep, VISIT which, void *closure), void *closure); void tdestroy(void *root, void (*free_node)(void *nodep));
说明
tsearch(),tfind(),twalk()和tdelete()管理二进制搜索树。它们是从Knuth(6.2.2)算法T推广而来的。树的每个节点中的第一个字段是指向相应数据项的指针。 (调用程序必须存储实际数据。)比较点指向比较例程,该例程需要指向两个项目的指针。它应返回一个负数,零值或正数的整数,具体取决于第一项是否小于,等于或大于第二项。
tsearch()在树中搜索项目。关键点指向要搜索的项目。 rootp指向一个变量,该变量指向树的根。如果树为空,则rootp指向的变量应设置为NULL。如果在树中找到该项目,则tsearch()返回一个指向相应树节点的指针。 (换句话说,tsearch()返回一个指向数据项的指针。)如果找不到该项目,则tsearch()将其添加,并返回一个指向相应树节点的指针。
tfind()类似于tsearch(),不同之处在于如果未找到该项目,则tfind()返回NULL。
tdelete()从树中删除一个项目。其参数与tsearch()相同。
twalk()执行二叉树的深度优先,从左到右遍历。根指向遍历的起始节点。如果该节点不是根节点,则仅访问树的一部分。每次访问节点时,twalk()都会调用用户函数操作(即,内部节点访问3次,叶子访问一次)。反过来,动作需要三个参数。第一个参数是指向要访问的节点的指针。节点的结构未指定,但是可以将指针转换为指向元素的指针,以访问存储在节点内的元素。应用程序不得修改此参数所指向的结构。第二个参数是一个整数,它取值顺序,后序或终止顺序之一,具体取决于这是对内部节点的第一次访问,第二次或第三次访问,或者值叶子(如果这是对叶子节点的单次访问) 。 (这些符号在中定义。)第三个参数是节点的深度。根节点的深度为零。
(更常见的是,预购,后购和终止购货被称为预购,订购和后购:在拜访孩子之前,第一次之后,第二次之前以及拜访孩子之后。因此,对名字postorder的选择相当混乱。 )
twalk_r()与twalk()类似,但是不使用depth参数,而是将闭合参数指针传递给操作回调的每次调用,而不会更改。该指针可用于以线程安全的方式在回调函数之间传递信息,而无需求助于全局变量。
tdestroy()删除根指向的整个树,从而释放tsearch()函数分配的所有资源。对于每个树节点中的数据,将调用函数free_node。指向数据的指针作为函数的参数传递。如果不需要进行此类工作,则free_node必须指向不执行任何操作的函数。
返回值
tsearch()返回指向树中匹配节点或新添加节点的指针,如果没有足够的内存来添加该项,则返回NULL。 tfind()返回指向该节点的指针,如果找不到匹配项,则返回NULL。如果有多个与键匹配的项目,则未指定返回节点的项目。
tdelete()返回指向已删除节点的父节点的指针,如果未找到该项目,则返回NULL。如果删除的节点是根节点,则tdelete()返回一个不能访问的悬空指针。
如果rootp在输入时为NULL,则tsearch(),tfind()和tdelete()也会返回NULL。
版本
从2.30版开始,glibc中提供了twalk_r()。
属性
有关本节中使用的术语的说明,请参见attribute(7)。
Interface | Attribute | Value |
tsearch(),tfind(), tdelete() | Thread safety | MT-Safe race:rootp |
twalk() | Thread safety | MT-Safe race:root |
twalk_r() | Thread safety | MT-Safe race:root |
tdestroy() | Thread safety | MT-Safe |
遵循规范
POSIX.1-2001,POSIX.1-2008,SVr4。函数tdestroy()和twalk_r()是GNU扩展。
备注
twalk()使用指向根的指针,而其他函数使用指向指向根的变量的指针。
tdelete()释放树中节点所需的内存。用户负责为相应的数据释放内存。
该示例程序取决于以下事实:在使用参数" endorder"或" leaf"调用用户函数后,twalk()不再进一步引用节点。这适用于GNU库实现,但System V文档中没有。
示例
下面的程序将十二个随机数插入二叉树中,其中重复的数字被折叠,然后按顺序打印数字。
#define _GNU_SOURCE /* Expose declaration of tdestroy() */ #include <search.h> #include <stdlib.h> #include <stdio.h> #include <time.h> static void *root = NULL; static void * xmalloc(unsigned n) { void *p; p = malloc(n); if (p) return p; fprintf(stderr, "insufficient memory\n"); exit(EXIT_FAILURE); } static int compare(const void *pa, const void *pb) { if (*(int *) pa < *(int *) pb) return -1; if (*(int *) pa > *(int *) pb) return 1; return 0; } static void action(const void *nodep, VISIT which, int depth) { int *datap; switch (which) { case preorder: break; case postorder: datap = *(int **) nodep; printf("%6d\n", *datap); break; case endorder: break; case leaf: datap = *(int **) nodep; printf("%6d\n", *datap); break; } } int main(void) { int i, *ptr; void *val; srand(time(NULL)); for (i = 0; i < 12; i++) { ptr = xmalloc(sizeof(int)); *ptr = rand() & 0xff; val = tsearch((void *) ptr, &root, compare); if (val == NULL) exit(EXIT_FAILURE); else if ((*(int **) val) != ptr) free(ptr); } twalk(root, action); tdestroy(root, free); exit(EXIT_SUCCESS); }
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。