C 二叉树——代码跟踪
给定如下所示的二叉树,确定在调用函数A(根)的情况下访问如下所示二叉树节点的顺序。假设树节点和指针的定义如图所示。假设root是指向包含60的节点的指针。 我对这个问题的回答如下。对吗?我做错了什么?C 二叉树——代码跟踪,c,algorithm,data-structures,binary-search-tree,C,Algorithm,Data Structures,Binary Search Tree,给定如下所示的二叉树,确定在调用函数A(根)的情况下访问如下所示二叉树节点的顺序。假设树节点和指针的定义如图所示。假设root是指向包含60的节点的指针。 我对这个问题的回答如下。对吗?我做错了什么? 60 / \ 30 90
60
/ \
30 90
/ \ /
5 38 77
\ / / \
8 32 62 88
struct treeNode{
int data;
struct treeNode *left, *right:
{
struct treeNode *tree_ptr;
void A(struct treeNode *node_ptr){
if (node_ptr != NULL){
printf(“%d ,”,node_ptr->data);
B(node_ptr->left);
B(node_ptr->right);
}
}
void B(struct treeNode *node_ptr){
if (node_ptr != NULL) {
A(node_ptr->left);
printf(“%d ,”,node_ptr->data);
A(node_ptr->right);
}
}
回答:
在void A中,它表示要首先打印节点\u ptr->数据,以便打印60
然后函数调用B(node_ptr->left),然后在B中调用A(node_ptr->left),然后打印数据,数据为5。然后调用一个(node_ptr->right)返回到一个,打印数据,这样就可以打印8。现在我不太确定下一步该怎么做,但从逻辑上讲,打印30是有意义的,但我不确定ptr是如何从8到30的。然后,如果你继续使用相同的模式,38会被打印,32会被打印。
对于正确的子树。。。
90 77 62 88首先,您的代码中有很多错误。我猜应该是这样的:
struct treeNode{
int data;
struct treeNode *left, *right;
}
treeNode *tree_ptr;
void A(treeNode *node_ptr){
if (node_ptr != NULL){ /// this could be just if(node_ptr)
printf(“%d ,”,node_ptr->data);
B(node_ptr->left);
B(node_ptr->right);
}
}
void B(treeNode *node_ptr){
if (node_ptr != NULL) {
A(node_ptr->left);
printf(“%d ,”,node_ptr->data);
A(node_ptr->right);
}
}
A(60)
printf(60)
call B(60.left)
B(30)
call A(30.left)
A(5)
printf(5)
call B(5.left)
B(null)
call B(5.right)
B(8)
call A(8.left)
A(null)
printf(8)
call A(8.right)
A(null)
printf(30)
call A(30.right)
A(38)
...
您还混合了两种不同的遍历算法<代码>A()是预订单,
B()
是订单A()
和B()
应该自己调用,而不是彼此调用。(使用实数变量/函数名而不是A
、B
等的另一个原因。)首先,您的代码中有大量错误。我猜应该是这样的:
struct treeNode{
int data;
struct treeNode *left, *right;
}
treeNode *tree_ptr;
void A(treeNode *node_ptr){
if (node_ptr != NULL){ /// this could be just if(node_ptr)
printf(“%d ,”,node_ptr->data);
B(node_ptr->left);
B(node_ptr->right);
}
}
void B(treeNode *node_ptr){
if (node_ptr != NULL) {
A(node_ptr->left);
printf(“%d ,”,node_ptr->data);
A(node_ptr->right);
}
}
A(60)
printf(60)
call B(60.left)
B(30)
call A(30.left)
A(5)
printf(5)
call B(5.left)
B(null)
call B(5.right)
B(8)
call A(8.left)
A(null)
printf(8)
call A(8.right)
A(null)
printf(30)
call A(30.right)
A(38)
...
您还混合了两种不同的遍历算法<代码>A()是预订单,
B()
是订单A()
和B()
应该自己调用,而不是彼此调用。(使用实变量/函数名而不是A
、B
等的另一个原因。)只需随时间写出完整的执行堆栈即可。像这样:
A(60)
printf
B(30)
A(5)
...
printf
A(38)
...
B(90)
...
(树的其余部分留给读者作为练习。)
然后从上到下,写下printf语句的结果。只需随时间写出完整的执行堆栈。像这样:
A(60)
printf
B(30)
A(5)
...
printf
A(38)
...
B(90)
...
(树的其余部分留给读者作为练习。)
然后从上到下,写下printf语句的结果。
A
是预顺序遍历,而B
是顺序遍历
确定打印顺序的一个简单方法是查看如何访问节点本身。我通常在树的外部画一个轮廓(从根开始,根据首先遍历的子树向左或向右移动)。如果我在进行预排序遍历,那么每当我沿着节点的外部移动时,我都会打印出一个节点。如果我正在进行按顺序遍历,则仅当我移动到节点下时才打印出节点(当您查看按顺序遍历时,这是有意义的,因为您首先打印叶子;它们是绘制轮廓时移动到其下的第一个节点)。如果我正在进行后序遍历,则仅当我沿着节点的内部移动时,才会打印出节点
更新
在5和8之后打印出30的原因是您没有执行纯粹的预顺序遍历。您正在预顺序和顺序遍历之间跳跃
计算顺序的一个简单方法是,在跟踪代码的过程中,实际写下代码所经历的步骤(我经常使用钢笔/铅笔和纸将信息保存在一起)。例如,您可以这样编写调用堆栈:
struct treeNode{
int data;
struct treeNode *left, *right;
}
treeNode *tree_ptr;
void A(treeNode *node_ptr){
if (node_ptr != NULL){ /// this could be just if(node_ptr)
printf(“%d ,”,node_ptr->data);
B(node_ptr->left);
B(node_ptr->right);
}
}
void B(treeNode *node_ptr){
if (node_ptr != NULL) {
A(node_ptr->left);
printf(“%d ,”,node_ptr->data);
A(node_ptr->right);
}
}
A(60)
printf(60)
call B(60.left)
B(30)
call A(30.left)
A(5)
printf(5)
call B(5.left)
B(null)
call B(5.right)
B(8)
call A(8.left)
A(null)
printf(8)
call A(8.right)
A(null)
printf(30)
call A(30.right)
A(38)
...
您可以很容易地看到节点的打印顺序,更重要的是,您为什么要从打印8“跳”到打印30(一个递归调用已经结束,您正在后退一级)。
A
是一个预顺序遍历,而B
是一个顺序遍历
确定打印顺序的一个简单方法是查看如何访问节点本身。我通常在树的外部画一个轮廓(从根开始,根据首先遍历的子树向左或向右移动)。如果我在进行预排序遍历,那么每当我沿着节点的外部移动时,我都会打印出一个节点。如果我正在进行按顺序遍历,则仅当我移动到节点下时才打印出节点(当您查看按顺序遍历时,这是有意义的,因为您首先打印叶子;它们是绘制轮廓时移动到其下的第一个节点)。如果我正在进行后序遍历,则仅当我沿着节点的内部移动时,才会打印出节点
更新
在5和8之后打印出30的原因是您没有执行纯粹的预顺序遍历。您正在预顺序和顺序遍历之间跳跃
计算顺序的一个简单方法是,在跟踪代码的过程中,实际写下代码所经历的步骤(我经常使用钢笔/铅笔和纸将信息保存在一起)。例如,您可以这样编写调用堆栈:
struct treeNode{
int data;
struct treeNode *left, *right;
}
treeNode *tree_ptr;
void A(treeNode *node_ptr){
if (node_ptr != NULL){ /// this could be just if(node_ptr)
printf(“%d ,”,node_ptr->data);
B(node_ptr->left);
B(node_ptr->right);
}
}
void B(treeNode *node_ptr){
if (node_ptr != NULL) {
A(node_ptr->left);
printf(“%d ,”,node_ptr->data);
A(node_ptr->right);
}
}
A(60)
printf(60)
call B(60.left)
B(30)
call A(30.left)
A(5)
printf(5)
call B(5.left)
B(null)
call B(5.right)
B(8)
call A(8.left)
A(null)
printf(8)
call A(8.right)
A(null)
printf(30)
call A(30.right)
A(38)
...
您可以很容易地看到节点的打印顺序,更重要的是,您为什么从打印8“跳”到打印30(一个递归调用已结束,您正在后退一级)。上述跟踪对于预订单或顺序都不正确 60岁之前、30岁之前、5岁之前、8岁之前、35岁之前等
在-5、8、30、32、35等中,上述跟踪对于预订单或订单都不正确 60岁之前、30岁之前、5岁之前、8岁之前、35岁之前等
在-5、8、30、32、35等中您可能应该将其标记为
作业
。不鼓励使用AFAIK作业
标记。给出的代码不会编译。你到底是什么意思?@Vivin,但如果一个问题被诚实地标记为这样的话,我很可能会正确地给出我的答案。@nmichaels基本上是提供的代码,因此决定了元素的打印顺序。我只是想验证一下,看看我是否正确。你可能应该把它标记为家庭作业