【发布时间】:2016-12-09 21:53:07
【问题描述】:
我正在尝试在 C 中创建一个 n 元树。我遇到了递归填充树的问题。我希望你能帮忙。
实现依赖于两个函数 insert_child 和 append_child 已经过测试并且可以工作。
我正在尝试递归地构建一棵二叉树。通过将子节点附加和插入到 main 中创建的根节点来手动构建它。如前所述,如果节点中已经存在子节点,则取决于 insert_child(),如果节点中不存在子节点,则取决于 append_child()。
它当前永远不会停止运行,并且不会输出 1 表示成功。
整个程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_SIZE 85
#define MAX_NODES 50
#define MAX_CHILDREN 5
// Data
typedef struct {
int library_choice;
double probability;
int child_id; // unique id from 1-n (total)
int child_index; // index from left in node from 1-n
int kr; // Antal Kr. Kun available in some cases
int utility; // Kun available in if Leafnode
} d_child;
typedef struct {
int node_index; // From 1-n for each level (resets)
int node_id; // unique id from 1-n (total)
int n_children; // Number of children in level
d_child d_child[MAX_CHILDREN];
} d_node;
typedef struct {
int level_id; // From 1-n
int player; // From 1-n
int n_nodes; // From 1-n
d_node d_node[MAX_NODES];
} d_level;
// Tree
typedef struct s_nary_node {
d_level data; // nodes data -> comes in index for the level
int n; // the number of children
struct s_nary_node **child; // the child list
} nary_node;
typedef nary_node nary_tree;
nary_tree *create_node(int children, d_level *data, int i) {
// allocate space for new nary_node
nary_node *node = (nary_node*)calloc(1, sizeof(nary_node));
// Set the contents of the NODE
node->data = data[i];
node->n = children;
node->child = (nary_node**)calloc(children, sizeof(nary_node*));
return node;
}
int append_child(nary_node *root, d_level *data, int i) {
// Increment the degree of the node
root->n++;
// Reallocate the child array (n children in the child array)
root->child = (nary_node **)realloc(root->child,(root->n)*sizeof(nary_node*));
// Add the newNode into the child array and increment degree
root->child[root->n - 1] = create_node(0, data, i);
// Return the index of the child we just inserted
return root->n - 1;
}
int insert_child(nary_node *root, int idx, d_level *data, int i) {
int j;
// First we make space
root->n++;
root->child = (nary_node**)realloc(root->child, (root->n)*sizeof(nary_node*));
for(j=root->n-1; j>idx; --j)
root->child[j] = root->child[j-1];
root->child[j] = create_node(0, data, i);
return j;
}
int create_tree(nary_node *root, d_level *data, int i) {
int j = 1;
if(root->n == 0) return 0; // Terminating condition
else {
for(j=1; j<root->n+1; j++) { // For every nodes children
printf("Hey\n");
if(root->child[j] == NULL) {
append_child(root, data, i);
}
else {
insert_child(root, j, data, i);
}
i++; // Count up level for data
root = root->child[j];
create_tree(root, data, i);
}
return 1;
}
}
// Data
int count_levels() {
int count = 0;
FILE *input_file;
input_file = fopen("data.xml", "r");
if(input_file == NULL) { printf("Could not open file\n"); }
else {
char temp[MAX_LINE_SIZE];
char level[] = "<level";
while(fgets(temp, MAX_LINE_SIZE, input_file)!= NULL) {
if(strstr(temp, level) != NULL) {
count++;
}
}
}
return count;
}
void read_level_data(d_level *d_level){
char temp[MAX_LINE_SIZE];
char level[] = "<level";
int i = 1;
// Opening file
FILE *input_file;
input_file = fopen("data.xml", "r");
if(input_file == NULL) { printf("Could not open file\n"); }
else {
while(fgets(temp, MAX_LINE_SIZE, input_file)!= NULL){
if(strstr(temp, level)) {
sscanf(temp, "<level id=\"%d\" player=\"%d\" nNodes=\"%d\">", &d_level[i].level_id, &d_level[i].player, &d_level[i].n_nodes);
i++;
}
}
}
}
void read_node_data(d_level *d_level){
char temp[MAX_LINE_SIZE];
char node[] = "<node";
char end_node[] = "</node";
char end_level[] = "</level>";
int i = 1;
int j = 1;
// Opening file
FILE *input_file;
input_file = fopen("data.xml", "r");
if(input_file == NULL) { printf("Could not open file\n"); }
else {
while(fgets(temp, MAX_LINE_SIZE, input_file)!= NULL){
if(strstr(temp, node)) {
sscanf(temp, " <node idx=\"%d\" id=\"%d\" nChildren=\"%d\">", &d_level[i].d_node[j].node_index, &d_level[i].d_node[j].node_id, &d_level[i].d_node[j].n_children);
}
else if(strstr(temp, end_node)) {
j++;
}
else if(strstr(temp, end_level)) {
i++;
j = 1; // reset nodecount for each iteration
}
}
}
}
void read_child_data(d_level *d_level){
char temp[MAX_LINE_SIZE];
char child[] = "<child";
char library_choice[] ="<libraryChoice";
char probability[] = "<probability";
char utility[] = "<probability";
char kr[] = "<kr";
char end_child[] = "</child";
char end_node[] = "</node";
char end_level[] = "</level";
int i = 1;
int j = 1;
int k = 1;
// Opening file
FILE *input_file;
input_file = fopen("data.xml", "r");
if(input_file == NULL) { printf("Could not open file\n"); }
else {
while(fgets(temp, MAX_LINE_SIZE, input_file)!= NULL){
if(strstr(temp, child)) {
sscanf(temp, " <child idx=\"%d\" id=\"%d\">", &d_level[i].d_node[j].d_child[k].child_index, &d_level[i].d_node[j].d_child[k].child_id);
}
else if(strstr(temp,library_choice)) {
sscanf(temp, " <libraryChoice>%d</libraryChoice>", &d_level[i].d_node[j].d_child[k].library_choice);
}
else if(strstr(temp,probability)) {
sscanf(temp, " <probability>%lf</probability>", &d_level[i].d_node[j].d_child[k].probability);
}
else if(strstr(temp,utility)) {
sscanf(temp, " <utility>%d</utility>", &d_level[i].d_node[j].d_child[k].utility);
}
else if(strstr(temp,kr)) {
sscanf(temp, " <kr>%d</kr>", &d_level[i].d_node[j].d_child[k].kr);
}
else if(strstr(temp, end_child)) { // </child
k++;
}
else if(strstr(temp, end_node)) { // </node
j++;
k = 1;
}
else if(strstr(temp, end_level)) { // </level
i++;
j = 1;
}
}
}
}
int main(void) {
// Data
d_level *d_level = calloc(count_levels(), sizeof(1, d_level));
// Read level data
read_level_data(d_level);
// Read node data
read_node_data(d_level);
// Read children data
read_child_data(d_level);
int i = 1;
nary_tree* root = (nary_node*)calloc(count_levels(),sizeof(nary_node));
root = create_node(2, d_level, i);
nary_tree* temp = (nary_node*)calloc(count_levels(),sizeof(nary_node));
temp = root;
int success = create_tree(temp, d_level, i);
printf("Return value: %d\n", success);
}
我正在解析的 XML 输入:
<level id="1" player="1" nNodes="1">
<node idx="1" id="1" nChildren="2">
<child idx="1" id="1">
<libraryChoice>1</libraryChoice>
<kr>1000</kr>
</child>
<child idx="2" id="2">
<libraryChoice>2</libraryChoice>
<kr>2000</kr>
</child>
</node>
</level>
<level id="2" player="2" nNodes="2">
<node idx="1" id="2" nChildren="2">
<child idx="1" id="3">
<libraryChoice>1</libraryChoice>
<probability>50.0</probability>
</child>
<child idx="2" id="4">
<libraryChoice>2</libraryChoice>
<probability>50.0</probability>
</child>
</node>
<node idx="2" id="3" nChildren="2">
<child idx="1" id="5">
<libraryChoice>3</libraryChoice>
<probability>50.0</probability>
<utility>-100</utility>
<kr>3000</kr>
</child>
<child idx="2" id="6">
<libraryChoice>4</libraryChoice>
<probability>50.0</probability>
<utility>100</utility>
<kr>4000</kr>
</child>
</node>
</level>
<level id="3" player="1" nNodes="2">
<node idx="1" id="4" nChildren="0">
</node>
<node idx="2" id="5" nChildren="0">
</node>
<node idx="3" id="6" nChildren="0">
</node>
<node idx="4" id="7" nChildren="0">
</node>
</level>
【问题讨论】:
-
什么是
nary_node?你的问题是什么?请阅读此minimal reproducible example。 -
我很抱歉不够清晰。该函数无限运行,不会按预期创建树。
-
目前还不清楚你想要什么:也读一下How to ask a good question
-
请发minimal reproducible example,这意味着您的代码可以轻松复制粘贴和编译。如果你的程序需要输入,也可以发布。
-
root 和 temp 获得分配的值 (calloc),并在下一行分配另一个值?