如何遍历多路树
How to tree traversal a multiway tree
我尝试过遍历多路树,但我正在尝试以一种有效的方式进行,但这并没有真正帮助我,更重要的是我想递归地进行。
我的想法是这样的:我有一棵树,一棵 child 和它的兄弟姐妹。我想用 childs 递归地向下移动,然后只要它有兄弟姐妹也可以递归地向下移动它们。
在这里我将向您展示我的数据结构以及我是如何尝试实现它的。这是一个完整的功能 "testable",它还将创建一张照片供您查看树并使用代码:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define SIZE 100
typedef struct tree {
int value;
struct tree *child, *sibling;
} *Tree;
Tree initTree(int value) {
Tree root = malloc(sizeof(struct tree));
root->value = value;
root->child = NULL;
root->sibling = NULL;
return root;
}
void drawTreeHelper(Tree tree, FILE* stream) {
Tree tmp;
if (tree == NULL) {
return;
}
fprintf(stream, " %ld[label=\"%d\", fillcolor=red]\n", (intptr_t) tree, tree->value);
tmp = tree->child;
while (tmp != NULL) {
fprintf(stream, " %ld -> %ld \n", (intptr_t) tree, (intptr_t) tmp);
drawTreeHelper(tmp, stream);
tmp = tmp->sibling;
}
}
void drawTree(Tree tree, char *fileName) {
FILE* stream = fopen("test.dot", "w");
char buffer[SIZE];
fprintf(stream, "digraph tree {\n");
fprintf(stream, " node [fontname=\"Arial\", shape=circle, style=filled, fillcolor=yellow];\n");
if (tree == NULL)
fprintf(stream, "\n");
else if (!tree->child)
fprintf(stream, " %ld [label=\"%d\"];\n", (intptr_t) tree, tree->value);
else
drawTreeHelper(tree, stream);
fprintf(stream, "}\n");
fclose(stream);
sprintf(buffer, "dot test.dot | neato -n -Tpng -o %s", fileName);
system(buffer);
}
int main() {
int i;
char buffer[SIZE];
Tree *forest = malloc(5 * sizeof(Tree));
for (i = 0; i < 5; i++) {
forest[i] = initTree(i);
}
forest[4]->child = forest[3];
forest[4]->child->sibling = forest[2];
forest[1]->child = forest[0];
forest[1]->child->sibling = forest[4];
for (i = 0; i < 5; i++) {
sprintf(buffer, "tree_%d.png", i);
if (forest[i]) {
drawTree(forest[i], buffer);
}
}
return 0;
}
我要创建的函数保持不变,即:
Tree findChild(Tree root, int value)
{
if(!root) return NULL;
if(root->value == value) return root;
return findChild(root->child, value);
Trie iter = root;
while(iter)
{
return findChild(iter->sibling, value);
iter = iter->sibling;
}
}
我希望找到 child,但如果节点不是根的直接 child,它 returns 我 NULL。
我要创建的功能的期望:在树中以最有效的方式找到child。
这是你的功能:
Tree findChild(Tree root, int value)
{
if(!root) return NULL;
if(root->value == value) return root;
这里,你向下遍历子节点,你却说return
!
return findChild(root->child, value);
所以这段代码永远不会执行:
Tree iter = root;
while(iter)
{
return findChild(iter->sibling, value);
iter = iter->sibling;
}
}
此外,迭代是无用的,因为您无论如何都要通过调用 findChild
遍历下一个兄弟节点。所以函数应该是这样的:
Tree findChild(Tree root, int value)
{
if(!root) return NULL;
if(root->value == value) return root;
Tree *ret = findChild(root->child, value);
if (!ret)
ret = findChild(root->sibling, value);
return ret;
}
这应该会如您所愿。
编辑:
在(无条件的)return
之后,代码永远不会执行。 "get around" return.
根本就没有代码路径
这可能是最有效的方法(就运行时复杂性而言)如果树中的项目不遵循特定顺序。如果树是有序的,您可以通过查看当前项目,将其与搜索的项目进行比较,然后 - 根据比较结果 - 仅选择两个路径之一 child
或 sibling
而不是遍历两者。
我尝试过遍历多路树,但我正在尝试以一种有效的方式进行,但这并没有真正帮助我,更重要的是我想递归地进行。
我的想法是这样的:我有一棵树,一棵 child 和它的兄弟姐妹。我想用 childs 递归地向下移动,然后只要它有兄弟姐妹也可以递归地向下移动它们。
在这里我将向您展示我的数据结构以及我是如何尝试实现它的。这是一个完整的功能 "testable",它还将创建一张照片供您查看树并使用代码:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define SIZE 100
typedef struct tree {
int value;
struct tree *child, *sibling;
} *Tree;
Tree initTree(int value) {
Tree root = malloc(sizeof(struct tree));
root->value = value;
root->child = NULL;
root->sibling = NULL;
return root;
}
void drawTreeHelper(Tree tree, FILE* stream) {
Tree tmp;
if (tree == NULL) {
return;
}
fprintf(stream, " %ld[label=\"%d\", fillcolor=red]\n", (intptr_t) tree, tree->value);
tmp = tree->child;
while (tmp != NULL) {
fprintf(stream, " %ld -> %ld \n", (intptr_t) tree, (intptr_t) tmp);
drawTreeHelper(tmp, stream);
tmp = tmp->sibling;
}
}
void drawTree(Tree tree, char *fileName) {
FILE* stream = fopen("test.dot", "w");
char buffer[SIZE];
fprintf(stream, "digraph tree {\n");
fprintf(stream, " node [fontname=\"Arial\", shape=circle, style=filled, fillcolor=yellow];\n");
if (tree == NULL)
fprintf(stream, "\n");
else if (!tree->child)
fprintf(stream, " %ld [label=\"%d\"];\n", (intptr_t) tree, tree->value);
else
drawTreeHelper(tree, stream);
fprintf(stream, "}\n");
fclose(stream);
sprintf(buffer, "dot test.dot | neato -n -Tpng -o %s", fileName);
system(buffer);
}
int main() {
int i;
char buffer[SIZE];
Tree *forest = malloc(5 * sizeof(Tree));
for (i = 0; i < 5; i++) {
forest[i] = initTree(i);
}
forest[4]->child = forest[3];
forest[4]->child->sibling = forest[2];
forest[1]->child = forest[0];
forest[1]->child->sibling = forest[4];
for (i = 0; i < 5; i++) {
sprintf(buffer, "tree_%d.png", i);
if (forest[i]) {
drawTree(forest[i], buffer);
}
}
return 0;
}
我要创建的函数保持不变,即:
Tree findChild(Tree root, int value)
{
if(!root) return NULL;
if(root->value == value) return root;
return findChild(root->child, value);
Trie iter = root;
while(iter)
{
return findChild(iter->sibling, value);
iter = iter->sibling;
}
}
我希望找到 child,但如果节点不是根的直接 child,它 returns 我 NULL。 我要创建的功能的期望:在树中以最有效的方式找到child。
这是你的功能:
Tree findChild(Tree root, int value)
{
if(!root) return NULL;
if(root->value == value) return root;
这里,你向下遍历子节点,你却说return
!
return findChild(root->child, value);
所以这段代码永远不会执行:
Tree iter = root;
while(iter)
{
return findChild(iter->sibling, value);
iter = iter->sibling;
}
}
此外,迭代是无用的,因为您无论如何都要通过调用 findChild
遍历下一个兄弟节点。所以函数应该是这样的:
Tree findChild(Tree root, int value)
{
if(!root) return NULL;
if(root->value == value) return root;
Tree *ret = findChild(root->child, value);
if (!ret)
ret = findChild(root->sibling, value);
return ret;
}
这应该会如您所愿。
编辑:
在(无条件的)return
之后,代码永远不会执行。 "get around" return.
这可能是最有效的方法(就运行时复杂性而言)如果树中的项目不遵循特定顺序。如果树是有序的,您可以通过查看当前项目,将其与搜索的项目进行比较,然后 - 根据比较结果 - 仅选择两个路径之一 child
或 sibling
而不是遍历两者。