【问题标题】:twalk without globals没有全局变量的 twalk
【发布时间】:2012-11-21 09:19:45
【问题描述】:

我正在尝试使用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)? 原谅我的英语不好

编辑: 正如 unwind 所说,解决方案是重新发明这个特定的轮子,重新定义 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");

【问题讨论】:

    标签: c binary-tree tree-traversal


    【解决方案1】:

    我想没有人能准确地回答“为什么”,除了那些指定和实现这些功能的人。我猜是“短视”,或者可能是“历史原因”(他们在线程编程成为普遍事物之前就这样做了)。

    无论如何,由于这个限制,这个 API 对我来说似乎有点“玩具”,事实上,所有未能包含用户拥有的 void * 的 API 都只是在 API 和任何回调之间不透明地传递。

    所以,我想的解决方案是重新发明这个特定的轮子,并编写自己的函数来遍历二叉树。

    【讨论】:

      【解决方案2】:

      您可以使用thread-local storage 来使用全局变量并且仍然是线程安全的。显然,您可以为此目的使用 __thread 关键字。还要检查Using __thread in c99

      【讨论】:

        猜你喜欢
        • 2012-04-29
        • 2020-10-29
        • 2017-12-12
        • 1970-01-01
        • 2016-10-03
        • 2021-06-21
        • 2015-08-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多