我正在尝试使用带有twalk()
<search.h>
遍历二叉树
#define _GNU_SOURCE /* Expose declaration of tdestroy() */
#include <search.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void *root = NULL;
void *
xmalloc(unsigned n)
{
void *p;
p = malloc(n);
if (p)
return p;
fprintf(stderr, "insufficient memory\n");
exit(EXIT_FAILURE);
}
int
compare(const void *pa, const void *pb)
{
if (*(int *) pa < *(int *) pb)
return -1;
if (*(int *) pa > *(int *) pb)
return 1;
return 0;
}
void
action(const void *nodep, const VISIT which, const 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 = (int *) 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);
}
如您所见,无法从action()传递或返回任何变量。 为什么这么密封?我不能使用任何全局因为程序使用线程,我的问题是:如何在线程安全模式下遍历(并与非全局变量共享nodep)? 请原谅我可怜的英语
修改 正如展开所说,解决方案是重新发明这个特定的轮子,重新定义tsearch.c使用的结构解决问题:
/* twalk() fake */
struct node_t
{
const void *key;
struct node_t *left;
struct node_t *right;
unsigned int red:1;
};
static void tmycallback(const xdata *data, const void *misc)
{
printf("%s %s\n", (const char *)misc, data->value);
}
static void tmywalk(const struct node_t *root, void (*callback)(const xdata *, const void *), const void *misc)
{
if (root->left == NULL && root->right == NULL) {
callback(*(xdata * const *)root, misc);
} else {
if (root->left != NULL) tmywalk(root->left, callback, misc);
callback(*(xdata * const *)root, misc);
if (root->right != NULL) tmywalk(root->right, callback, misc);
}
}
/* END twalk() fake */
if (root) tmywalk(root, tmycallback, "Hello walker");
答案 0 :(得分:4)
我想没有人可以完全回答“为什么”,除了那些指定和实现这些功能的人。我猜“短视”,或者可能是“历史原因”(他们在线程编程变得普遍之前就已经做过了。)
无论如何,由于这种限制,这个API对我来说似乎有点“玩具”,事实上所有API都不包含用户拥有的void *
,它只是在API和任何回调之间不透明地传递
所以,我想解决方案是重新发明这个特定的轮子,并编写自己的函数来遍历二叉树。
答案 1 :(得分:1)
您可以使用thread-local storage来使用全局变量,但仍然是线程安全的。显然,您可以使用__thread
关键字来实现此目的。另请查看Using __thread in c99。