问题描述
#include <stdio.h>
#include <stdlib.h>
节点创建
此结构创建结构节点数据类型
struct node
{
int data;
struct node *left,*right;
} * newnode;
创建函数
create()
- 它首先分配节点所需的内存。当用户输入数据时,它递归地调用自己来创建它的子节点,这个过程继续下去。当用户输入 -1 时,它终止递归并从调用处返回。
struct node *create()
{
int x;
newnode = (struct node *)malloc(sizeof(struct node));
newnode->left = 0;
newnode->right = 0;
printf("Enter data(-1 for no node)\n");
scanf("%d",&x);
if (x == -1)
return 0;
newnode->data = x;
printf("Enter left child of %d\n",x);
newnode->left = create();
printf("Enter right child of %d\n",x);
newnode->right = create();
return newnode;
}
预购
preorder(struct node *root)
- 此函数以预序方式显示树的数据
void preorder(struct node *root)
{
if (root == 0)
return;
printf("%d\n",root->data);
preorder(root->left);
preorder(root->right);
}
中序
inorder(struct node *root)
- 此函数按顺序显示树的数据
void inorder(struct node *root)
{
if (root == 0)
return;
inorder(root->left);
printf("%d\n",root->data);
inorder(root->right);
}
后序
postorder(struct node *root)
- 此函数以后序方式显示树的数据
void postorder(struct node *root)
{
if (root == 0)
return;
postorder(root->left);
postorder(root->right);
printf("%d\n",root->data);
}
主要功能
Main 函数要求用户创建一棵树,然后根据用户输入的选择遍历它。问题是 preorder、inorder 和 postorder 没有给出所需的输出,并导致执行后无限循环。
void main()
{
struct node *root;
root = 0;
int choice = 3,opt = 1;
while (opt)
{
printf("Select\n 1-for creation\n 2-for preorder\n 3-for inorder\n 4-for postorder\n");
scanf("%d",&choice);
switch (choice)
{
case 1:
root = create();
break;
case 2:
printf("Preorder is: ");
preorder(root);
break;
case 3:
printf("Inorder is: ");
inorder(root);
break;
case 4:
printf("postorder is: ");
postorder(root);
break;
default:
printf("Invalid choice");
break;
}
printf("Wanna continue \n1-for yes\n0-for no\n");
scanf("%d",&opt);
}
}
解决方法
您提供的任何遍历函数都没有错误。
create ()
函数也没有设计或实现问题。
问题在于使用结构定义声明的全局 struct node
指针 newnode
。
因为每次对 create ()
的递归调用基本上都使用“相同的”newnode
指针,所以树从未真正按照我们想要的方式构建。
让我们尝试试运行 create ()
函数。
假设我们想要一棵这样的树:
1
/ \
2 3
-
create ()
首先从main
调用。
- 使用
malloc ()
函数分配内存,内存地址存储在newnode
中。 - 设置它的属性,
left
和right
。 - 请求
data
并将其放入data
属性中,如果data == -1
为真,则return 0
。
到目前为止,这是状态:
newnode -> 1
/ \
Null Null
-
create ()
被递归调用以构建左子树。
-
使用
newnode
为malloc ()
分配内存,内存地址存放在newnode
中。请注意,此操作基本上“覆盖”了先前存储在newnode
中的地址(因为newnode
是一个全局变量) -
然后,将再次提示用户输入
data
并设置其属性。
因此,这棵树现在变成了:
newnode -> 2
/ \
Null Null
struct node
之前指向的 newnode
现在丢失了(因为丢失了它的地址)
同样,当递归调用右子树时,将观察到以下情况:
newnode -> 3
/ \
Null Null
考虑到其余递归调用的相同场景,很明显,最终没有构建我们期望的树,原因是全局变量 {{1 }},不断分配内存并覆盖newnode
中的地址只会导致内存泄漏。
发现无限递归的原因是,在多次递归调用期间,newnode
的 left
或 right
指针指向newnode
本身,导致一个循环。可以通过在递归调用期间密切跟踪 newnode
的 data
来找到该节点。
因此,从结构声明中删除newnode
指针的声明并修改newnode
函数中的以下语句:
create ()
为此:
newnode = (struct node *)malloc(sizeof(struct node));
和
struct node * newnode = (struct node *)malloc(sizeof(struct node));
就是需要的一切。
这样每次对struct node
{
int data;
struct node *left,*right;
};
函数的递归调用都会有自己的局部指针变量create ()
,不会有覆盖、无泄漏、无循环、无无限递归。