假設我有以下節點圖的所有節點:如何寫一個foreach般的宏來訪問圖形
typedef struct node node_t;
struct node {
size_t adjacent_node_count;
node_t **adjacent_nodes;
void* data;
};
該圖表示爲一個指向其中一個節點(即,我沒有所有節點的單個列表,但是每個節點都保證可以從這個「根」節點到達)。
現在,我需要訪問此圖中的每個節點,並將其中的每個節點的data
只應用一次函數一次。我想最簡單的方法就是DFS。
讓我們添加一些的Fileds到node
簡化實施
typedef struct node node_t;
struct node {
size_t adjacent_node_count;
node_t **adjacent_nodes;
void* data;
node_t *dfs_stack_next;
bool dfs_visited;
};
而且穿越本身就是
void dfs(node_t *root, void* context, void (*function)(void* context, void* data)) {
node_t *stack_top = root;
while (stack_top != NULL) {
node_t *current_node = stack_top;
stack_top = stack_top->dfs_stack_next;
if (!current_node->dfs_visited) {
current_node->dfs_visited = true;
for (int i = 0; i < current_node->adjacent_node_count; ++i) {
node_t *adjacent_node = current_node->adjacent_nodes[i];
adjacent_node->dfs_stack_next = stack_top;
stack_top = adjacent_node;
}
function(context, current_node->data);
}
}
}
這是failry簡單。但是寫功能和結構包裹當地情況變得痛苦快,所以我想在foreach
樣宏來包裝這個:
for_each_node(n, root) {
// do stuff with n->data
}
我在循環中部分入門頂級節點從堆棧
#define for_each_node(current_node, root) \
for (state_t *current_node, *stack_top = root; \
stack_top \
? (current_node = stack_top, stack_top = stack_top->dfs_stack_next, stack_top) \
: stack_top; \
) /* ??? */
現在我被卡住了。我意識到,這是相當簡單的寫了兩個部分的宏,像
for_each_node_begin(n, root)
// do stuff with n->data
for_each_node_end(n, root)
,將簡單的兩線與function
通話分裂dfs
,但是我發現,相當難看。
那麼,我該如何去執行for_each_node
?這是否可能?它不需要是DFS,任何訂單都可以,只要data
被處理一次。