А вот задачка...

Oct 16, 2009 12:19

...любопытная кстати. Хотя бы тем, что я не могу сообразить, как ее сделать прямо.

Надо состыковать два интерфейса для обхода дерева, суть токова:

У нас есть такой:

typedef struct _node_ node_t;

typedef int (*callback)( node_t *node, void *context );

int bypass_tree( node_t *root, callback cb, void *context );
а надо поверх него ( Read more... )

c, problem, code, iterator, callback, call/cc

Leave a comment

Comments 15

mxax October 16 2009, 08:46:56 UTC
Полюбас надо где-то хранить стейт bypass_tree(), либо во внешней структуре, либо, опять же, POSIX makecontext()/swapcontext().

Reply


_winnie October 16 2009, 09:08:46 UTC
longjmp не умеет возвращаться к убитому стеку.
Имхо в C не получится, если только не завести другие OS-потоки.

Reply

mxax October 16 2009, 09:10:07 UTC
В C как раз получится, man makecontext, man swapcontext, как я сказал уже выше.

Reply

_winnie October 16 2009, 09:17:05 UTC
Ну, если не нужна компиляция в Visual C++ под Windows, то получится.

Reply

mxax October 16 2009, 09:22:21 UTC
Под винду есть куча реализаций или можно использовать те же fibers, но они тяжелее.

Reply


_winnie October 16 2009, 09:24:09 UTC
Кстати, да. Теоретически, можно писать непортабельный код без потоков, через Windows Fiber API/ POSIX swapcontext

Reply

swizard October 16 2009, 09:42:20 UTC
Класс, первая же ссылка по запросу Windows Fiber API как раз посвящена моей проблеме :) http://www.ddj.com/cpp/184401766

Reply


ext_69439 October 17 2009, 19:51:28 UTC
Зачем массив?
Любое дерево имеет строгую иерархию такую, что имея произвольную ноду можно легко получить предыдущий или последующий элемент. Это справедливо как для бинарных деревьев, так и для tries.
Если брать, например бинарное дерево, будь то avl-tree или rb-tree, то алгоритм будет такой:
Для next:
Если у ноды есть правая нода, то следующим элементом будет самая левая нода правого поддерева или сама правая нода, если у той отсутвует левое поддерево.

В противном случае, следуюшим элементом будет та нода, для которой исходная нода находится в левом поддереве.

node_t *bin_tree_next(node_t *n)
{
if (n->right) {
for (n = n->right; n->left; n = n->left);
}
else {
note_t *tmp = n;
while (tmp->parent && tmp == tmp->parent->right) {
tmp = tmp->parent;
}
if (tmp == n) {
n = NULL;
}
else {
n = tmp->parent;
}
}

return n;
}

Зеркальное отражение bin_tree_next - bin_tree_prev.

Reply

swizard October 17 2009, 21:48:24 UTC
Да это все понятно, но задача не в том :)

Внутрь реализации я залезть не могу, мне нужно четко написать адаптер между двумя такими интерфейсами.

Reply


cmm October 19 2009, 17:05:45 UTC
наваять классический inversion of control на Ц - это богато, да.

поглядите как реализован call/cc в SCM или Guile - отвратительно по сути (setjmp/longjmp + копирование стека кучу и обратно), но не так уж сложно и туеву хучу лет вполне себе работает.

ну или можно действительно по-индийски сделать, поскольку любое решение не через call/cc (или моральный аналог на тредах или фиберах) потребует так или иначе прошерстить всё дерево.

Reply


Leave a comment

Up